blob: bd29e8a287645b21334be26f443b1f95983e1385 [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/',
danakjc8576092019-11-26 19:01:36387 '^jingle/',
danakj7a2b7082019-05-21 21:13:51388 '^media/audio/',
389 '^media/base/',
danakjc8576092019-11-26 19:01:36390 '^media/blink/',
danakj7a2b7082019-05-21 21:13:51391 '^media/capture/',
392 '^media/cast/',
393 '^media/cdm/',
394 '^media/device_monitors/',
395 '^media/ffmpeg/',
396 '^media/filters/',
397 '^media/formats/',
398 '^media/gpu/',
399 '^media/mojo/',
400 '^media/muxers/',
401 '^media/remoting/',
402 '^media/renderers/',
403 '^media/test/',
danakj7a2b7082019-05-21 21:13:51404 '^mojo/public/',
405 '^net/',
406 '^ppapi/proxy/',
407 '^ppapi/shared_impl/',
408 '^ppapi/tests/',
409 '^ppapi/thunk/',
410 '^remoting/base/',
411 '^remoting/client/',
412 '^remoting/codec/',
413 '^remoting/host/',
414 '^remoting/internal/',
415 '^remoting/ios/',
416 '^remoting/protocol/',
417 '^remoting/signaling/',
418 '^remoting/test/',
danakj7a2b7082019-05-21 21:13:51419 '^services/',
420 '^storage/browser/',
danakj7a2b7082019-05-21 21:13:51421 '^third_party/blink/',
422 '^third_party/crashpad/crashpad/test/gtest_main.cc',
423 '^third_party/leveldatabase/leveldb_chrome.cc',
424 '^third_party/boringssl/gtest_main_chromium.cc',
425 '^third_party/cacheinvalidation/overrides/' +
426 'google/cacheinvalidation/deps/callback.h',
427 '^third_party/libaddressinput/chromium/chrome_address_validator.cc',
428 '^third_party/zlib/google/',
429 '^tools/android/',
430 '^tools/clang/base_bind_rewriters/', # Intentional.
431 '^tools/gdb/gdb_chrome.py', # Intentional.
432 '^ui/accelerated_widget_mac/',
danakj7a2b7082019-05-21 21:13:51433 '^ui/base/',
434 '^ui/compositor/',
435 '^ui/display/',
danakjc8576092019-11-26 19:01:36436 '^weblayer/',
danakj7a2b7082019-05-21 21:13:51437))
[email protected]127f18ec2012-06-16 05:05:59438
Daniel Bratell609102be2019-03-27 20:53:21439# Format: Sequence of tuples containing:
440# * String pattern or, if starting with a slash, a regular expression.
441# * Sequence of strings to show when the pattern matches.
442# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
443# * Sequence of paths to *not* check (regexps).
[email protected]127f18ec2012-06-16 05:05:59444_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20445 (
Dave Tapuska98199b612019-07-10 13:30:44446 r'/\bNULL\b',
thomasandersone7caaa9b2017-03-29 19:22:53447 (
448 'New code should not use NULL. Use nullptr instead.',
449 ),
Mohamed Amir Yosefea381072019-08-09 08:13:20450 False,
thomasandersone7caaa9b2017-03-29 19:22:53451 (),
452 ),
Peter Kasting94a56c42019-10-25 21:54:04453 (
454 r'/\busing namespace ',
455 (
456 'Using directives ("using namespace x") are banned by the Google Style',
457 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
458 'Explicitly qualify symbols or use using declarations ("using x::foo").',
459 ),
460 True,
461 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
462 ),
Antonio Gomes07300d02019-03-13 20:59:57463 # Make sure that gtest's FRIEND_TEST() macro is not used; the
464 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
465 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53466 (
[email protected]23e6cbc2012-06-16 18:51:20467 'FRIEND_TEST(',
468 (
[email protected]e3c945502012-06-26 20:01:49469 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20470 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
471 ),
472 False,
[email protected]7345da02012-11-27 14:31:49473 (),
[email protected]23e6cbc2012-06-16 18:51:20474 ),
475 (
Dave Tapuska98199b612019-07-10 13:30:44476 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53477 (
478 'Chrome clients wishing to select events on X windows should use',
479 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
480 'you are selecting events from the GPU process, or if you are using',
481 'an XDisplay other than gfx::GetXDisplay().',
482 ),
483 True,
484 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40485 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04486 r"^ui[\\/]gl[\\/].*\.cc$",
487 r"^media[\\/]gpu[\\/].*\.cc$",
488 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53489 ),
490 ),
491 (
Dave Tapuska98199b612019-07-10 13:30:44492 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20493 (
thomasanderson11aa41d2017-06-08 22:22:38494 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20495 ),
496 True,
497 (
Egor Paskoce145c42018-09-28 19:31:04498 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
499 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
500 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20501 ),
502 ),
503 (
tomhudsone2c14d552016-05-26 17:07:46504 'setMatrixClip',
505 (
506 'Overriding setMatrixClip() is prohibited; ',
507 'the base function is deprecated. ',
508 ),
509 True,
510 (),
511 ),
512 (
[email protected]52657f62013-05-20 05:30:31513 'SkRefPtr',
514 (
515 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22516 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31517 ),
518 True,
519 (),
520 ),
521 (
522 'SkAutoRef',
523 (
524 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22525 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31526 ),
527 True,
528 (),
529 ),
530 (
531 'SkAutoTUnref',
532 (
533 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22534 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31535 ),
536 True,
537 (),
538 ),
539 (
540 'SkAutoUnref',
541 (
542 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
543 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22544 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31545 ),
546 True,
547 (),
548 ),
[email protected]d89eec82013-12-03 14:10:59549 (
550 r'/HANDLE_EINTR\(.*close',
551 (
552 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
553 'descriptor will be closed, and it is incorrect to retry the close.',
554 'Either call close directly and ignore its return value, or wrap close',
555 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
556 ),
557 True,
558 (),
559 ),
560 (
561 r'/IGNORE_EINTR\((?!.*close)',
562 (
563 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
564 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
565 ),
566 True,
567 (
568 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04569 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
570 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59571 ),
572 ),
[email protected]ec5b3f02014-04-04 18:43:43573 (
574 r'/v8::Extension\(',
575 (
576 'Do not introduce new v8::Extensions into the code base, use',
577 'gin::Wrappable instead. See http://crbug.com/334679',
578 ),
579 True,
[email protected]f55c90ee62014-04-12 00:50:03580 (
Egor Paskoce145c42018-09-28 19:31:04581 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03582 ),
[email protected]ec5b3f02014-04-04 18:43:43583 ),
skyostilf9469f72015-04-20 10:38:52584 (
jame2d1a952016-04-02 00:27:10585 '#pragma comment(lib,',
586 (
587 'Specify libraries to link with in build files and not in the source.',
588 ),
589 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41590 (
tzik3f295992018-12-04 20:32:23591 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04592 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41593 ),
jame2d1a952016-04-02 00:27:10594 ),
fdorayc4ac18d2017-05-01 21:39:59595 (
Gabriel Charette7cc6c432018-04-25 20:52:02596 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59597 (
598 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
599 ),
600 False,
601 (),
602 ),
603 (
Gabriel Charette7cc6c432018-04-25 20:52:02604 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59605 (
606 'Consider using THREAD_CHECKER macros instead of the class directly.',
607 ),
608 False,
609 (),
610 ),
dbeamb6f4fde2017-06-15 04:03:06611 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06612 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
613 (
614 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
615 'deprecated (http://crbug.com/634507). Please avoid converting away',
616 'from the Time types in Chromium code, especially if any math is',
617 'being done on time values. For interfacing with platform/library',
618 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
619 'type converter methods instead. For faking TimeXXX values (for unit',
620 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
621 'other use cases, please contact base/time/OWNERS.',
622 ),
623 False,
624 (),
625 ),
626 (
dbeamb6f4fde2017-06-15 04:03:06627 'CallJavascriptFunctionUnsafe',
628 (
629 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
630 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
631 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
632 ),
633 False,
634 (
Egor Paskoce145c42018-09-28 19:31:04635 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
636 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
637 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06638 ),
639 ),
dskiba1474c2bfd62017-07-20 02:19:24640 (
641 'leveldb::DB::Open',
642 (
643 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
644 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
645 "Chrome's tracing, making their memory usage visible.",
646 ),
647 True,
648 (
649 r'^third_party/leveldatabase/.*\.(cc|h)$',
650 ),
Gabriel Charette0592c3a2017-07-26 12:02:04651 ),
652 (
Chris Mumfordc38afb62017-10-09 17:55:08653 'leveldb::NewMemEnv',
654 (
655 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58656 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
657 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08658 ),
659 True,
660 (
661 r'^third_party/leveldatabase/.*\.(cc|h)$',
662 ),
663 ),
664 (
Gabriel Charetted9839bc2017-07-29 14:17:47665 'RunLoop::QuitCurrent',
666 (
Robert Liao64b7ab22017-08-04 23:03:43667 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
668 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47669 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41670 False,
Gabriel Charetted9839bc2017-07-29 14:17:47671 (),
Gabriel Charettea44975052017-08-21 23:14:04672 ),
673 (
674 'base::ScopedMockTimeMessageLoopTaskRunner',
675 (
Gabriel Charette87cc1af2018-04-25 20:52:51676 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11677 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51678 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
679 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
680 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04681 ),
Gabriel Charette87cc1af2018-04-25 20:52:51682 False,
Gabriel Charettea44975052017-08-21 23:14:04683 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57684 ),
685 (
Dave Tapuska98199b612019-07-10 13:30:44686 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57687 (
688 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02689 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57690 ),
691 True,
692 (),
Francois Doray43670e32017-09-27 12:40:38693 ),
694 (
Peter Kasting991618a62019-06-17 22:00:09695 r'/\bstd::stoi\b',
696 (
697 'std::stoi uses exceptions to communicate results. ',
698 'Use base::StringToInt() instead.',
699 ),
700 True,
701 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
702 ),
703 (
704 r'/\bstd::stol\b',
705 (
706 'std::stol uses exceptions to communicate results. ',
707 'Use base::StringToInt() instead.',
708 ),
709 True,
710 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
711 ),
712 (
713 r'/\bstd::stoul\b',
714 (
715 'std::stoul uses exceptions to communicate results. ',
716 'Use base::StringToUint() instead.',
717 ),
718 True,
719 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
720 ),
721 (
722 r'/\bstd::stoll\b',
723 (
724 'std::stoll uses exceptions to communicate results. ',
725 'Use base::StringToInt64() instead.',
726 ),
727 True,
728 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
729 ),
730 (
731 r'/\bstd::stoull\b',
732 (
733 'std::stoull uses exceptions to communicate results. ',
734 'Use base::StringToUint64() instead.',
735 ),
736 True,
737 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
738 ),
739 (
740 r'/\bstd::stof\b',
741 (
742 'std::stof uses exceptions to communicate results. ',
743 'For locale-independent values, e.g. reading numbers from disk',
744 'profiles, use base::StringToDouble().',
745 'For user-visible values, parse using ICU.',
746 ),
747 True,
748 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
749 ),
750 (
751 r'/\bstd::stod\b',
752 (
753 'std::stod uses exceptions to communicate results. ',
754 'For locale-independent values, e.g. reading numbers from disk',
755 'profiles, use base::StringToDouble().',
756 'For user-visible values, parse using ICU.',
757 ),
758 True,
759 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
760 ),
761 (
762 r'/\bstd::stold\b',
763 (
764 'std::stold uses exceptions to communicate results. ',
765 'For locale-independent values, e.g. reading numbers from disk',
766 'profiles, use base::StringToDouble().',
767 'For user-visible values, parse using ICU.',
768 ),
769 True,
770 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
771 ),
772 (
Daniel Bratell69334cc2019-03-26 11:07:45773 r'/\bstd::to_string\b',
774 (
775 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09776 'For locale-independent strings, e.g. writing numbers to disk',
777 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45778 'For user-visible strings, use base::FormatNumber() and',
779 'the related functions in base/i18n/number_formatting.h.',
780 ),
Peter Kasting991618a62019-06-17 22:00:09781 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21782 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45783 ),
784 (
785 r'/\bstd::shared_ptr\b',
786 (
787 'std::shared_ptr should not be used. Use scoped_refptr instead.',
788 ),
789 True,
Andreas Haas63f58792019-11-07 10:56:44790 [_THIRD_PARTY_EXCEPT_BLINK,
791 '^third_party/blink/renderer/core/typed_arrays/array_buffer/' +
792 'array_buffer_contents\.(cc|h)'],
Daniel Bratell609102be2019-03-27 20:53:21793 ),
794 (
Peter Kasting991618a62019-06-17 22:00:09795 r'/\bstd::weak_ptr\b',
796 (
797 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
798 ),
799 True,
800 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
801 ),
802 (
Daniel Bratell609102be2019-03-27 20:53:21803 r'/\blong long\b',
804 (
805 'long long is banned. Use stdint.h if you need a 64 bit number.',
806 ),
807 False, # Only a warning since it is already used.
808 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
809 ),
810 (
811 r'/\bstd::bind\b',
812 (
813 'std::bind is banned because of lifetime risks.',
814 'Use base::BindOnce or base::BindRepeating instead.',
815 ),
816 True,
817 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
818 ),
819 (
820 r'/\b#include <chrono>\b',
821 (
822 '<chrono> overlaps with Time APIs in base. Keep using',
823 'base classes.',
824 ),
825 True,
826 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
827 ),
828 (
829 r'/\b#include <exception>\b',
830 (
831 'Exceptions are banned and disabled in Chromium.',
832 ),
833 True,
834 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
835 ),
836 (
837 r'/\bstd::function\b',
838 (
839 'std::function is banned. Instead use base::Callback which directly',
840 'supports Chromium\'s weak pointers, ref counting and more.',
841 ),
Peter Kasting991618a62019-06-17 22:00:09842 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21843 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
844 ),
845 (
846 r'/\b#include <random>\b',
847 (
848 'Do not use any random number engines from <random>. Instead',
849 'use base::RandomBitGenerator.',
850 ),
851 True,
852 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
853 ),
854 (
855 r'/\bstd::ratio\b',
856 (
857 'std::ratio is banned by the Google Style Guide.',
858 ),
859 True,
860 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45861 ),
862 (
Francois Doray43670e32017-09-27 12:40:38863 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
864 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
865 (
866 'Use the new API in base/threading/thread_restrictions.h.',
867 ),
Gabriel Charette04b138f2018-08-06 00:03:22868 False,
Francois Doray43670e32017-09-27 12:40:38869 (),
870 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38871 (
danakj7a2b7082019-05-21 21:13:51872 r'/\bbase::Bind\(',
873 (
874 'Please use base::Bind{Once,Repeating} instead',
875 'of base::Bind. (crbug.com/714018)',
876 ),
877 False,
Erik Staaba737d7602019-11-25 18:41:07878 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51879 ),
880 (
881 r'/\bbase::Callback[<:]',
882 (
883 'Please use base::{Once,Repeating}Callback instead',
884 'of base::Callback. (crbug.com/714018)',
885 ),
886 False,
Erik Staaba737d7602019-11-25 18:41:07887 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51888 ),
889 (
890 r'/\bbase::Closure\b',
891 (
892 'Please use base::{Once,Repeating}Closure instead',
893 'of base::Closure. (crbug.com/714018)',
894 ),
895 False,
Erik Staaba737d7602019-11-25 18:41:07896 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51897 ),
898 (
Michael Giuffrida7f93d6922019-04-19 14:39:58899 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19900 (
901 'RunMessageLoop is deprecated, use RunLoop instead.',
902 ),
903 False,
904 (),
905 ),
906 (
Dave Tapuska98199b612019-07-10 13:30:44907 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19908 (
909 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
910 ),
911 False,
912 (),
913 ),
914 (
Dave Tapuska98199b612019-07-10 13:30:44915 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19916 (
917 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
918 "if you're convinced you need this.",
919 ),
920 False,
921 (),
922 ),
923 (
Dave Tapuska98199b612019-07-10 13:30:44924 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19925 (
926 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:04927 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:19928 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
929 'async events instead of flushing threads.',
930 ),
931 False,
932 (),
933 ),
934 (
935 r'MessageLoopRunner',
936 (
937 'MessageLoopRunner is deprecated, use RunLoop instead.',
938 ),
939 False,
940 (),
941 ),
942 (
Dave Tapuska98199b612019-07-10 13:30:44943 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19944 (
945 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
946 "gab@ if you found a use case where this is the only solution.",
947 ),
948 False,
949 (),
950 ),
951 (
Victor Costane48a2e82019-03-15 22:02:34952 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:16953 (
Victor Costane48a2e82019-03-15 22:02:34954 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:16955 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
956 ),
957 True,
958 (
959 r'^sql/initialization\.(cc|h)$',
960 r'^third_party/sqlite/.*\.(c|cc|h)$',
961 ),
962 ),
Matt Menke7f520a82018-03-28 21:38:37963 (
964 'net::URLFetcher',
965 (
966 'net::URLFetcher should no longer be used in content embedders. ',
967 'Instead, use network::SimpleURLLoader instead, which supports ',
968 'an out-of-process network stack. ',
969 'net::URLFetcher may still be used in binaries that do not embed',
970 'content.',
971 ),
Matt Menke59716d02018-04-05 12:45:53972 False,
Matt Menke7f520a82018-03-28 21:38:37973 (
Egor Paskoce145c42018-09-28 19:31:04974 r'^ios[\\/].*\.(cc|h)$',
975 r'.*[\\/]ios[\\/].*\.(cc|h)$',
Matt Menke7f520a82018-03-28 21:38:37976 r'.*_ios\.(cc|h)$',
Egor Paskoce145c42018-09-28 19:31:04977 r'^net[\\/].*\.(cc|h)$',
978 r'.*[\\/]tools[\\/].*\.(cc|h)$',
Fabrice de Gans-Riberi9345311c2019-08-30 23:33:43979 r'^fuchsia/base/test_devtools_list_fetcher\.cc$',
Matt Menke7f520a82018-03-28 21:38:37980 ),
981 ),
jdoerried7d10ab2018-04-27 10:46:13982 (
Dave Tapuska98199b612019-07-10 13:30:44983 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:47984 (
985 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
986 'base::RandomShuffle instead.'
987 ),
988 True,
989 (),
990 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:24991 (
992 'ios/web/public/test/http_server',
993 (
994 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
995 ),
996 False,
997 (),
998 ),
Robert Liao764c9492019-01-24 18:46:28999 (
1000 'GetAddressOf',
1001 (
1002 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Robert Liaoe794041e2019-10-03 17:16:461003 'implicated in a few leaks. Use operator& instead. See ',
1004 'http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:281005 ),
1006 True,
1007 (),
1008 ),
Antonio Gomes07300d02019-03-13 20:59:571009 (
1010 'DEFINE_TYPE_CASTS',
1011 (
1012 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
1013 '//third_party/blink/renderer/platform/casting.h.'
1014 ),
1015 True,
1016 (
1017 r'^third_party/blink/renderer/.*\.(cc|h)$',
1018 ),
1019 ),
Carlos Knippschildab192b8c2019-04-08 20:02:381020 (
Abhijeet Kandalkar1e7c2502019-10-29 15:05:451021 r'/\bIsHTML.+Element\(\b',
1022 (
1023 'Function IsHTMLXXXXElement is deprecated. Instead, use downcast ',
1024 ' helpers IsA<HTMLXXXXElement> from ',
1025 '//third_party/blink/renderer/platform/casting.h.'
1026 ),
1027 False,
1028 (
1029 r'^third_party/blink/renderer/.*\.(cc|h)$',
1030 ),
1031 ),
1032 (
1033 r'/\bToHTML.+Element(|OrNull)\(\b',
1034 (
1035 'Function ToHTMLXXXXElement and ToHTMLXXXXElementOrNull are '
1036 'deprecated. Instead, use downcast helpers To<HTMLXXXXElement> '
1037 'and DynamicTo<HTMLXXXXElement> from ',
1038 '//third_party/blink/renderer/platform/casting.h.'
1039 'auto* html_xxxx_ele = To<HTMLXXXXElement>(n)'
1040 'auto* html_xxxx_ele_or_null = DynamicTo<HTMLXXXXElement>(n)'
1041 ),
1042 False,
1043 (
1044 r'^third_party/blink/renderer/.*\.(cc|h)$',
1045 ),
1046 ),
1047 (
Kinuko Yasuda376c2ce12019-04-16 01:20:371048 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381049 (
1050 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1051 ),
1052 True,
1053 (),
1054 ),
Ben Lewisa9514602019-04-29 17:53:051055 (
1056 'SHFileOperation',
1057 (
1058 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1059 'complex functions to achieve the same goals. Use IFileOperation for ',
1060 'any esoteric actions instead.'
1061 ),
1062 True,
1063 (),
1064 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181065 (
Cliff Smolinsky81951642019-04-30 21:39:511066 'StringFromGUID2',
1067 (
1068 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1069 'Use base::win::String16FromGUID instead.'
1070 ),
1071 True,
1072 (
1073 r'/base/win/win_util_unittest.cc'
1074 ),
1075 ),
1076 (
1077 'StringFromCLSID',
1078 (
1079 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1080 'Use base::win::String16FromGUID instead.'
1081 ),
1082 True,
1083 (
1084 r'/base/win/win_util_unittest.cc'
1085 ),
1086 ),
1087 (
Avi Drissman7382afa02019-04-29 23:27:131088 'kCFAllocatorNull',
1089 (
1090 'The use of kCFAllocatorNull with the NoCopy creation of ',
1091 'CoreFoundation types is prohibited.',
1092 ),
1093 True,
1094 (),
1095 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291096 (
1097 'mojo::ConvertTo',
1098 (
1099 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1100 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1101 'StringTraits if you would like to convert between custom types and',
1102 'the wire format of mojom types.'
1103 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221104 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291105 (
Wezf89dec092019-09-11 19:38:331106 r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
1107 r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291108 r'^third_party/blink/.*\.(cc|h)$',
1109 r'^content/renderer/.*\.(cc|h)$',
1110 ),
1111 ),
Robert Liao1d78df52019-11-11 20:02:011112 (
1113 'CComPtr',
1114 (
1115 'New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1116 'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1117 'details.'
1118 ),
1119 False,
1120 (),
1121 ),
[email protected]127f18ec2012-06-16 05:05:591122)
1123
Mario Sanchez Prada2472cab2019-09-18 10:58:311124# Format: Sequence of tuples containing:
1125# * String pattern or, if starting with a slash, a regular expression.
1126# * Sequence of strings to show when the pattern matches.
1127_DEPRECATED_MOJO_TYPES = (
1128 (
1129 r'/\bmojo::AssociatedBinding\b',
1130 (
1131 'mojo::AssociatedBinding<Interface> is deprecated.',
1132 'Use mojo::AssociatedReceiver<Interface> instead.',
1133 ),
1134 ),
1135 (
1136 r'/\bmojo::AssociatedBindingSet\b',
1137 (
1138 'mojo::AssociatedBindingSet<Interface> is deprecated.',
1139 'Use mojo::AssociatedReceiverSet<Interface> instead.',
1140 ),
1141 ),
1142 (
1143 r'/\bmojo::AssociatedInterfacePtr\b',
1144 (
1145 'mojo::AssociatedInterfacePtr<Interface> is deprecated.',
1146 'Use mojo::AssociatedRemote<Interface> instead.',
1147 ),
1148 ),
1149 (
1150 r'/\bmojo::AssociatedInterfacePtrInfo\b',
1151 (
1152 'mojo::AssociatedInterfacePtrInfo<Interface> is deprecated.',
1153 'Use mojo::PendingAssociatedRemote<Interface> instead.',
1154 ),
1155 ),
1156 (
1157 r'/\bmojo::AssociatedInterfaceRequest\b',
1158 (
1159 'mojo::AssociatedInterfaceRequest<Interface> is deprecated.',
1160 'Use mojo::PendingAssociatedReceiver<Interface> instead.',
1161 ),
1162 ),
1163 (
1164 r'/\bmojo::Binding\b',
1165 (
1166 'mojo::Binding<Interface> is deprecated.',
1167 'Use mojo::Receiver<Interface> instead.',
1168 ),
1169 ),
1170 (
1171 r'/\bmojo::BindingSet\b',
1172 (
1173 'mojo::BindingSet<Interface> is deprecated.',
1174 'Use mojo::ReceiverSet<Interface> instead.',
1175 ),
1176 ),
1177 (
1178 r'/\bmojo::InterfacePtr\b',
1179 (
1180 'mojo::InterfacePtr<Interface> is deprecated.',
1181 'Use mojo::Remote<Interface> instead.',
1182 ),
1183 ),
1184 (
1185 r'/\bmojo::InterfacePtrInfo\b',
1186 (
1187 'mojo::InterfacePtrInfo<Interface> is deprecated.',
1188 'Use mojo::PendingRemote<Interface> instead.',
1189 ),
1190 ),
1191 (
1192 r'/\bmojo::InterfaceRequest\b',
1193 (
1194 'mojo::InterfaceRequest<Interface> is deprecated.',
1195 'Use mojo::PendingReceiver<Interface> instead.',
1196 ),
1197 ),
1198 (
1199 r'/\bmojo::MakeRequest\b',
1200 (
1201 'mojo::MakeRequest is deprecated.',
1202 'Use mojo::Remote::BindNewPipeAndPassReceiver() instead.',
1203 ),
1204 ),
1205 (
1206 r'/\bmojo::MakeRequestAssociatedWithDedicatedPipe\b',
1207 (
1208 'mojo::MakeRequest is deprecated.',
1209 'Use mojo::AssociatedRemote::'
1210 'BindNewEndpointAndPassDedicatedReceiverForTesting() instead.',
1211 ),
1212 ),
1213 (
1214 r'/\bmojo::MakeStrongBinding\b',
1215 (
1216 'mojo::MakeStrongBinding is deprecated.',
1217 'Either migrate to mojo::UniqueReceiverSet, if possible, or use',
1218 'mojo::MakeSelfOwnedReceiver() instead.',
1219 ),
1220 ),
1221 (
1222 r'/\bmojo::MakeStrongAssociatedBinding\b',
1223 (
1224 'mojo::MakeStrongAssociatedBinding is deprecated.',
1225 'Either migrate to mojo::UniqueAssociatedReceiverSet, if possible, or',
1226 'use mojo::MakeSelfOwnedAssociatedReceiver() instead.',
1227 ),
1228 ),
1229 (
1230 r'/\bmojo::StrongAssociatedBindingSet\b',
1231 (
1232 'mojo::StrongAssociatedBindingSet<Interface> is deprecated.',
1233 'Use mojo::UniqueAssociatedReceiverSet<Interface> instead.',
1234 ),
1235 ),
1236 (
1237 r'/\bmojo::StrongBindingSet\b',
1238 (
1239 'mojo::StrongBindingSet<Interface> is deprecated.',
1240 'Use mojo::UniqueReceiverSet<Interface> instead.',
1241 ),
1242 ),
1243)
wnwenbdc444e2016-05-25 13:44:151244
mlamouria82272622014-09-16 18:45:041245_IPC_ENUM_TRAITS_DEPRECATED = (
1246 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501247 'See http://www.chromium.org/Home/chromium-security/education/'
1248 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041249
Stephen Martinis97a394142018-06-07 23:06:051250_LONG_PATH_ERROR = (
1251 'Some files included in this CL have file names that are too long (> 200'
1252 ' characters). If committed, these files will cause issues on Windows. See'
1253 ' https://crbug.com/612667 for more details.'
1254)
1255
Shenghua Zhangbfaa38b82017-11-16 21:58:021256_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041257 r".*[\\/]BuildHooksAndroidImpl\.java",
1258 r".*[\\/]LicenseContentProvider\.java",
1259 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281260 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021261]
[email protected]127f18ec2012-06-16 05:05:591262
Mohamed Heikald048240a2019-11-12 16:57:371263# List of image extensions that are used as resources in chromium.
1264_IMAGE_EXTENSIONS = ['.svg', '.png', '.webp']
1265
Sean Kau46e29bc2017-08-28 16:31:161266# These paths contain test data and other known invalid JSON files.
1267_KNOWN_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041268 r'test[\\/]data[\\/]',
1269 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1270 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041271 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431272 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161273]
1274
1275
[email protected]b00342e7f2013-03-26 16:21:541276_VALID_OS_MACROS = (
1277 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081278 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541279 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121280 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541281 'OS_BSD',
1282 'OS_CAT', # For testing.
1283 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041284 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541285 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371286 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541287 'OS_IOS',
1288 'OS_LINUX',
1289 'OS_MACOSX',
1290 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211291 'OS_NACL_NONSFI',
1292 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121293 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541294 'OS_OPENBSD',
1295 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371296 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541297 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541298 'OS_WIN',
1299)
1300
1301
agrievef32bcc72016-04-04 14:57:401302_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391303 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361304 'base/android/jni_generator/jni_generator.pydeps',
1305 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221306 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361307 'build/android/gyp/aar.pydeps',
1308 'build/android/gyp/aidl.pydeps',
Tibor Goldschwendt0bef2d7a2019-10-24 21:19:271309 'build/android/gyp/allot_native_libraries.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361310 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381311 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361312 'build/android/gyp/bytecode_processor.pydeps',
1313 'build/android/gyp/compile_resources.pydeps',
Tibor Goldschwendt84ec04c2019-08-23 21:19:091314 'build/android/gyp/create_app_bundle_apks.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361315 'build/android/gyp/create_bundle_wrapper_script.pydeps',
1316 'build/android/gyp/copy_ex.pydeps',
1317 'build/android/gyp/create_app_bundle.pydeps',
1318 'build/android/gyp/create_apk_operations_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361319 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221320 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361321 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591322 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361323 'build/android/gyp/dex.pydeps',
1324 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361325 'build/android/gyp/filter_zip.pydeps',
1326 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361327 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361328 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581329 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361330 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261331 'build/android/gyp/java_cpp_strings.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361332 'build/android/gyp/javac.pydeps',
1333 'build/android/gyp/jinja_template.pydeps',
1334 'build/android/gyp/lint.pydeps',
1335 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361336 'build/android/gyp/merge_manifest.pydeps',
1337 'build/android/gyp/prepare_resources.pydeps',
1338 'build/android/gyp/proguard.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241339 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361340 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461341 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561342 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361343 'build/android/incremental_install/generate_android_manifest.pydeps',
1344 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221345 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401346 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041347 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361348 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411349 'chrome/android/features/create_stripped_java_factory.pydeps',
Tibor Goldschwendtc748dfca42019-10-24 19:39:051350 'components/module_installer/android/module_desc_java.pydeps',
agrieve732db3a2016-04-26 19:18:191351 'net/tools/testserver/testserver.pydeps',
Andrew Luo338fe6e82019-09-19 07:17:431352 'testing/scripts/run_android_wpt.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021353 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401354]
1355
wnwenbdc444e2016-05-25 13:44:151356
agrievef32bcc72016-04-04 14:57:401357_GENERIC_PYDEPS_FILES = [
anthonyvd7323c982019-09-11 14:36:421358 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131359 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:421360 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
1361 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131362 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
John Budorickbc3571aa2019-04-25 02:20:061363 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221364 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401365]
1366
wnwenbdc444e2016-05-25 13:44:151367
agrievef32bcc72016-04-04 14:57:401368_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1369
1370
Eric Boren6fd2b932018-01-25 15:05:081371# Bypass the AUTHORS check for these accounts.
1372_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:291373 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
1374 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
Eric Boren36af476a2018-06-08 16:21:081375 'fuchsia-sdk', 'nacl', 'pdfium', 'perfetto', 'skia',
Eric Boren57cc805b2018-08-20 17:28:321376 'spirv', 'src-internal', 'webrtc')
Sergiy Byelozyorov47158a52018-06-13 22:38:591377 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451378 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591379 ) | set('%[email protected]' % s
Robert Ma7f024172018-11-01 20:59:221380 for s in ('v8-ci-autoroll-builder', 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041381 ) | set('%[email protected]' % s
1382 for s in ('chromium-autoroll',)
1383 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301384 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081385
1386
Daniel Bratell65b033262019-04-23 08:17:061387def _IsCPlusPlusFile(input_api, file_path):
1388 """Returns True if this file contains C++-like code (and not Python,
1389 Go, Java, MarkDown, ...)"""
1390
1391 ext = input_api.os_path.splitext(file_path)[1]
1392 # This list is compatible with CppChecker.IsCppFile but we should
1393 # consider adding ".c" to it. If we do that we can use this function
1394 # at more places in the code.
1395 return ext in (
1396 '.h',
1397 '.cc',
1398 '.cpp',
1399 '.m',
1400 '.mm',
1401 )
1402
1403def _IsCPlusPlusHeaderFile(input_api, file_path):
1404 return input_api.os_path.splitext(file_path)[1] == ".h"
1405
1406
1407def _IsJavaFile(input_api, file_path):
1408 return input_api.os_path.splitext(file_path)[1] == ".java"
1409
1410
1411def _IsProtoFile(input_api, file_path):
1412 return input_api.os_path.splitext(file_path)[1] == ".proto"
1413
[email protected]55459852011-08-10 15:17:191414def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1415 """Attempts to prevent use of functions intended only for testing in
1416 non-testing code. For now this is just a best-effort implementation
1417 that ignores header files and may have some false positives. A
1418 better implementation would probably need a proper C++ parser.
1419 """
1420 # We only scan .cc files and the like, as the declaration of
1421 # for-testing functions in header files are hard to distinguish from
1422 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491423 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191424
jochenc0d4808c2015-07-27 09:25:421425 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191426 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091427 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191428 exclusion_pattern = input_api.re.compile(
1429 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1430 base_function_pattern, base_function_pattern))
1431
1432 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441433 black_list = (_EXCLUDED_PATHS +
1434 _TEST_CODE_EXCLUDED_PATHS +
1435 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191436 return input_api.FilterSourceFile(
1437 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491438 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191439 black_list=black_list)
1440
1441 problems = []
1442 for f in input_api.AffectedSourceFiles(FilterFile):
1443 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241444 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031445 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461446 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031447 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191448 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031449 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191450
1451 if problems:
[email protected]f7051d52013-04-02 18:31:421452 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031453 else:
1454 return []
[email protected]55459852011-08-10 15:17:191455
1456
Vaclav Brozek7dbc28c2018-03-27 08:35:231457def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1458 """This is a simplified version of
1459 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1460 """
1461 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1462 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1463 name_pattern = r'ForTest(s|ing)?'
1464 # Describes an occurrence of "ForTest*" inside a // comment.
1465 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1466 # Catch calls.
1467 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1468 # Ignore definitions. (Comments are ignored separately.)
1469 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1470
1471 problems = []
1472 sources = lambda x: input_api.FilterSourceFile(
1473 x,
1474 black_list=(('(?i).*test', r'.*\/junit\/')
1475 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491476 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231477 )
1478 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1479 local_path = f.LocalPath()
1480 is_inside_javadoc = False
1481 for line_number, line in f.ChangedContents():
1482 if is_inside_javadoc and javadoc_end_re.search(line):
1483 is_inside_javadoc = False
1484 if not is_inside_javadoc and javadoc_start_re.search(line):
1485 is_inside_javadoc = True
1486 if is_inside_javadoc:
1487 continue
1488 if (inclusion_re.search(line) and
1489 not comment_re.search(line) and
1490 not exclusion_re.search(line)):
1491 problems.append(
1492 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1493
1494 if problems:
1495 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1496 else:
1497 return []
1498
1499
[email protected]10689ca2011-09-02 02:31:541500def _CheckNoIOStreamInHeaders(input_api, output_api):
1501 """Checks to make sure no .h files include <iostream>."""
1502 files = []
1503 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1504 input_api.re.MULTILINE)
1505 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1506 if not f.LocalPath().endswith('.h'):
1507 continue
1508 contents = input_api.ReadFile(f)
1509 if pattern.search(contents):
1510 files.append(f)
1511
1512 if len(files):
yolandyandaabc6d2016-04-18 18:29:391513 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061514 'Do not #include <iostream> in header files, since it inserts static '
1515 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541516 '#include <ostream>. See http://crbug.com/94794',
1517 files) ]
1518 return []
1519
Danil Chapovalov3518f362018-08-11 16:13:431520def _CheckNoStrCatRedefines(input_api, output_api):
1521 """Checks no windows headers with StrCat redefined are included directly."""
1522 files = []
1523 pattern_deny = input_api.re.compile(
1524 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1525 input_api.re.MULTILINE)
1526 pattern_allow = input_api.re.compile(
1527 r'^#include\s"base/win/windows_defines.inc"',
1528 input_api.re.MULTILINE)
1529 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1530 contents = input_api.ReadFile(f)
1531 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1532 files.append(f.LocalPath())
1533
1534 if len(files):
1535 return [output_api.PresubmitError(
1536 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1537 'directly since they pollute code with StrCat macro. Instead, '
1538 'include matching header from base/win. See http://crbug.com/856536',
1539 files) ]
1540 return []
1541
[email protected]10689ca2011-09-02 02:31:541542
[email protected]72df4e782012-06-21 16:28:181543def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521544 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181545 problems = []
1546 for f in input_api.AffectedFiles():
1547 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1548 continue
1549
1550 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041551 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181552 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1553
1554 if not problems:
1555 return []
1556 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1557 '\n'.join(problems))]
1558
Dominic Battre033531052018-09-24 15:45:341559def _CheckNoDISABLETypoInTests(input_api, output_api):
1560 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1561
1562 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1563 instead of DISABLED_. To filter false positives, reports are only generated
1564 if a corresponding MAYBE_ line exists.
1565 """
1566 problems = []
1567
1568 # The following two patterns are looked for in tandem - is a test labeled
1569 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1570 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1571 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1572
1573 # This is for the case that a test is disabled on all platforms.
1574 full_disable_pattern = input_api.re.compile(
1575 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1576 input_api.re.MULTILINE)
1577
Katie Df13948e2018-09-25 07:33:441578 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341579 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1580 continue
1581
1582 # Search for MABYE_, DISABLE_ pairs.
1583 disable_lines = {} # Maps of test name to line number.
1584 maybe_lines = {}
1585 for line_num, line in f.ChangedContents():
1586 disable_match = disable_pattern.search(line)
1587 if disable_match:
1588 disable_lines[disable_match.group(1)] = line_num
1589 maybe_match = maybe_pattern.search(line)
1590 if maybe_match:
1591 maybe_lines[maybe_match.group(1)] = line_num
1592
1593 # Search for DISABLE_ occurrences within a TEST() macro.
1594 disable_tests = set(disable_lines.keys())
1595 maybe_tests = set(maybe_lines.keys())
1596 for test in disable_tests.intersection(maybe_tests):
1597 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1598
1599 contents = input_api.ReadFile(f)
1600 full_disable_match = full_disable_pattern.search(contents)
1601 if full_disable_match:
1602 problems.append(' %s' % f.LocalPath())
1603
1604 if not problems:
1605 return []
1606 return [
1607 output_api.PresubmitPromptWarning(
1608 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1609 '\n'.join(problems))
1610 ]
1611
[email protected]72df4e782012-06-21 16:28:181612
danakj61c1aa22015-10-26 19:55:521613def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571614 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521615 errors = []
1616 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1617 input_api.re.MULTILINE)
1618 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1619 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1620 continue
1621 for lnum, line in f.ChangedContents():
1622 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171623 errors.append(output_api.PresubmitError(
1624 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571625 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171626 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521627 return errors
1628
1629
Makoto Shimazu3ad422cd2019-05-08 02:35:141630def _FindHistogramNameInChunk(histogram_name, chunk):
1631 """Tries to find a histogram name or prefix in a line.
1632
1633 Returns the existence of the histogram name, or None if it needs more chunk
1634 to determine."""
mcasasb7440c282015-02-04 14:52:191635 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1636 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141637 if '<affected-histogram' in chunk:
1638 # If the tag is not completed, needs more chunk to get the name.
1639 if not '>' in chunk:
1640 return None
1641 if not 'name="' in chunk:
1642 return False
1643 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1644 # expect the only attribute is the name.
1645 histogram_prefix = chunk.split('"')[1]
1646 return histogram_prefix in histogram_name
1647 # Typically the whole histogram name should in the line.
1648 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191649
1650
1651def _CheckUmaHistogramChanges(input_api, output_api):
1652 """Check that UMA histogram names in touched lines can still be found in other
1653 lines of the patch or in histograms.xml. Note that this check would not catch
1654 the reverse: changes in histograms.xml not matched in the code itself."""
1655 touched_histograms = []
1656 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471657 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1658 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1659 name_pattern = r'"(.*?)"'
1660 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1661 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1662 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1663 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1664 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171665 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191666 for f in input_api.AffectedFiles():
1667 # If histograms.xml itself is modified, keep the modified lines for later.
1668 if f.LocalPath().endswith(('histograms.xml')):
1669 histograms_xml_modifications = f.ChangedContents()
1670 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471671 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1672 single_line_re = single_line_c_re
1673 split_line_prefix_re = split_line_c_prefix_re
1674 elif f.LocalPath().endswith(('java')):
1675 single_line_re = single_line_java_re
1676 split_line_prefix_re = split_line_java_prefix_re
1677 else:
mcasasb7440c282015-02-04 14:52:191678 continue
1679 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171680 if last_line_matched_prefix:
1681 suffix_found = split_line_suffix_re.search(line)
1682 if suffix_found :
1683 touched_histograms.append([suffix_found.group(1), f, line_num])
1684 last_line_matched_prefix = False
1685 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061686 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191687 if found:
1688 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171689 continue
1690 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191691
1692 # Search for the touched histogram names in the local modifications to
1693 # histograms.xml, and, if not found, on the base histograms.xml file.
1694 unmatched_histograms = []
1695 for histogram_info in touched_histograms:
1696 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141697 chunk = ''
mcasasb7440c282015-02-04 14:52:191698 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141699 chunk += line
1700 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1701 if histogram_name_found is None:
1702 continue
1703 chunk = ''
mcasasb7440c282015-02-04 14:52:191704 if histogram_name_found:
1705 break
1706 if not histogram_name_found:
1707 unmatched_histograms.append(histogram_info)
1708
eromanb90c82e7e32015-04-01 15:13:491709 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191710 problems = []
1711 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491712 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191713 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451714 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191715 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141716 chunk = ''
mcasasb7440c282015-02-04 14:52:191717 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141718 chunk += line
1719 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1720 chunk)
1721 if histogram_name_found is None:
1722 continue
1723 chunk = ''
mcasasb7440c282015-02-04 14:52:191724 if histogram_name_found:
1725 break
1726 if not histogram_name_found:
1727 problems.append(' [%s:%d] %s' %
1728 (f.LocalPath(), line_num, histogram_name))
1729
1730 if not problems:
1731 return []
1732 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1733 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491734 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191735
wnwenbdc444e2016-05-25 13:44:151736
yolandyandaabc6d2016-04-18 18:29:391737def _CheckFlakyTestUsage(input_api, output_api):
1738 """Check that FlakyTest annotation is our own instead of the android one"""
1739 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1740 files = []
1741 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1742 if f.LocalPath().endswith('Test.java'):
1743 if pattern.search(input_api.ReadFile(f)):
1744 files.append(f)
1745 if len(files):
1746 return [output_api.PresubmitError(
1747 'Use org.chromium.base.test.util.FlakyTest instead of '
1748 'android.test.FlakyTest',
1749 files)]
1750 return []
mcasasb7440c282015-02-04 14:52:191751
wnwenbdc444e2016-05-25 13:44:151752
[email protected]8ea5d4b2011-09-13 21:49:221753def _CheckNoNewWStrings(input_api, output_api):
1754 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271755 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221756 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201757 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571758 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341759 '/win/' in f.LocalPath() or
1760 'chrome_elf' in f.LocalPath() or
1761 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201762 continue
[email protected]8ea5d4b2011-09-13 21:49:221763
[email protected]a11dbe9b2012-08-07 01:32:581764 allowWString = False
[email protected]b5c24292011-11-28 14:38:201765 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581766 if 'presubmit: allow wstring' in line:
1767 allowWString = True
1768 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271769 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581770 allowWString = False
1771 else:
1772 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221773
[email protected]55463aa62011-10-12 00:48:271774 if not problems:
1775 return []
1776 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581777 ' If you are calling a cross-platform API that accepts a wstring, '
1778 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271779 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221780
1781
[email protected]2a8ac9c2011-10-19 17:20:441782def _CheckNoDEPSGIT(input_api, output_api):
1783 """Make sure .DEPS.git is never modified manually."""
1784 if any(f.LocalPath().endswith('.DEPS.git') for f in
1785 input_api.AffectedFiles()):
1786 return [output_api.PresubmitError(
1787 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1788 'automated system based on what\'s in DEPS and your changes will be\n'
1789 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501790 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1791 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441792 'for more information')]
1793 return []
1794
1795
tandriief664692014-09-23 14:51:471796def _CheckValidHostsInDEPS(input_api, output_api):
1797 """Checks that DEPS file deps are from allowed_hosts."""
1798 # Run only if DEPS file has been modified to annoy fewer bystanders.
1799 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1800 return []
1801 # Outsource work to gclient verify
1802 try:
John Budorickf20c0042019-04-25 23:23:401803 gclient_path = input_api.os_path.join(
1804 input_api.PresubmitLocalPath(),
1805 'third_party', 'depot_tools', 'gclient.py')
1806 input_api.subprocess.check_output(
1807 [input_api.python_executable, gclient_path, 'verify'],
1808 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471809 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201810 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471811 return [output_api.PresubmitError(
1812 'DEPS file must have only git dependencies.',
1813 long_text=error.output)]
1814
1815
Mario Sanchez Prada2472cab2019-09-18 10:58:311816def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
1817 type_name, message):
1818 """Helper method for _CheckNoBannedFunctions and _CheckNoDeprecatedMojoTypes.
1819
1820 Returns an string composed of the name of the file, the line number where the
1821 match has been found and the additional text passed as |message| in case the
1822 target type name matches the text inside the line passed as parameter.
1823 """
1824 matched = False
1825 if type_name[0:1] == '/':
1826 regex = type_name[1:]
1827 if input_api.re.search(regex, line):
1828 matched = True
1829 elif type_name in line:
1830 matched = True
1831
1832 result = []
1833 if matched:
1834 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
1835 for message_line in message:
1836 result.append(' %s' % message_line)
1837
1838 return result
1839
1840
[email protected]127f18ec2012-06-16 05:05:591841def _CheckNoBannedFunctions(input_api, output_api):
1842 """Make sure that banned functions are not used."""
1843 warnings = []
1844 errors = []
1845
wnwenbdc444e2016-05-25 13:44:151846 def IsBlacklisted(affected_file, blacklist):
1847 local_path = affected_file.LocalPath()
1848 for item in blacklist:
1849 if input_api.re.match(item, local_path):
1850 return True
1851 return False
1852
Peter K. Lee6c03ccff2019-07-15 14:40:051853 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541854 local_path = affected_file.LocalPath()
1855 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1856 return False
1857 basename = input_api.os_path.basename(local_path)
1858 if 'ios' in basename.split('_'):
1859 return True
1860 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1861 if sep and 'ios' in local_path.split(sep):
1862 return True
1863 return False
1864
wnwenbdc444e2016-05-25 13:44:151865 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
Mario Sanchez Prada2472cab2019-09-18 10:58:311866 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1867 func_name, message)
1868 if problems:
wnwenbdc444e2016-05-25 13:44:151869 if error:
Mario Sanchez Prada2472cab2019-09-18 10:58:311870 errors.extend(problems)
1871 else:
1872 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:151873
Eric Stevensona9a980972017-09-23 00:04:411874 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1875 for f in input_api.AffectedFiles(file_filter=file_filter):
1876 for line_num, line in f.ChangedContents():
1877 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1878 CheckForMatch(f, line_num, line, func_name, message, error)
1879
[email protected]127f18ec2012-06-16 05:05:591880 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1881 for f in input_api.AffectedFiles(file_filter=file_filter):
1882 for line_num, line in f.ChangedContents():
1883 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151884 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591885
Peter K. Lee6c03ccff2019-07-15 14:40:051886 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541887 for line_num, line in f.ChangedContents():
1888 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1889 CheckForMatch(f, line_num, line, func_name, message, error)
1890
Peter K. Lee6c03ccff2019-07-15 14:40:051891 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1892 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1893 for line_num, line in f.ChangedContents():
1894 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1895 CheckForMatch(f, line_num, line, func_name, message, error)
1896
[email protected]127f18ec2012-06-16 05:05:591897 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1898 for f in input_api.AffectedFiles(file_filter=file_filter):
1899 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491900 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491901 if IsBlacklisted(f, excluded_paths):
1902 continue
wnwenbdc444e2016-05-25 13:44:151903 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591904
1905 result = []
1906 if (warnings):
1907 result.append(output_api.PresubmitPromptWarning(
1908 'Banned functions were used.\n' + '\n'.join(warnings)))
1909 if (errors):
1910 result.append(output_api.PresubmitError(
1911 'Banned functions were used.\n' + '\n'.join(errors)))
1912 return result
1913
1914
Mario Sanchez Prada2472cab2019-09-18 10:58:311915def _CheckNoDeprecatedMojoTypes(input_api, output_api):
1916 """Make sure that old Mojo types are not used."""
1917 warnings = []
1918
1919 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1920 for f in input_api.AffectedFiles(file_filter=file_filter):
1921 # Only need to check Blink for warnings for now.
1922 if not f.LocalPath().startswith('third_party/blink'):
1923 continue
1924
1925 for line_num, line in f.ChangedContents():
1926 for func_name, message in _DEPRECATED_MOJO_TYPES:
1927 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1928 func_name, message)
1929 if problems:
1930 warnings.extend(problems)
1931
1932 result = []
1933 if (warnings):
1934 result.append(output_api.PresubmitPromptWarning(
1935 'Banned Mojo types were used.\n' + '\n'.join(warnings)))
1936 return result
1937
1938
[email protected]6c063c62012-07-11 19:11:061939def _CheckNoPragmaOnce(input_api, output_api):
1940 """Make sure that banned functions are not used."""
1941 files = []
1942 pattern = input_api.re.compile(r'^#pragma\s+once',
1943 input_api.re.MULTILINE)
1944 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1945 if not f.LocalPath().endswith('.h'):
1946 continue
1947 contents = input_api.ReadFile(f)
1948 if pattern.search(contents):
1949 files.append(f)
1950
1951 if files:
1952 return [output_api.PresubmitError(
1953 'Do not use #pragma once in header files.\n'
1954 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1955 files)]
1956 return []
1957
[email protected]127f18ec2012-06-16 05:05:591958
[email protected]e7479052012-09-19 00:26:121959def _CheckNoTrinaryTrueFalse(input_api, output_api):
1960 """Checks to make sure we don't introduce use of foo ? true : false."""
1961 problems = []
1962 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1963 for f in input_api.AffectedFiles():
1964 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1965 continue
1966
1967 for line_num, line in f.ChangedContents():
1968 if pattern.match(line):
1969 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1970
1971 if not problems:
1972 return []
1973 return [output_api.PresubmitPromptWarning(
1974 'Please consider avoiding the "? true : false" pattern if possible.\n' +
1975 '\n'.join(problems))]
1976
1977
[email protected]55f9f382012-07-31 11:02:181978def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:281979 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:181980 change. Breaking - rules is an error, breaking ! rules is a
1981 warning.
1982 """
mohan.reddyf21db962014-10-16 12:26:471983 import sys
[email protected]55f9f382012-07-31 11:02:181984 # We need to wait until we have an input_api object and use this
1985 # roundabout construct to import checkdeps because this file is
1986 # eval-ed and thus doesn't have __file__.
1987 original_sys_path = sys.path
1988 try:
1989 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:471990 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:181991 import checkdeps
[email protected]55f9f382012-07-31 11:02:181992 from rules import Rule
1993 finally:
1994 # Restore sys.path to what it was before.
1995 sys.path = original_sys_path
1996
1997 added_includes = []
rhalavati08acd232017-04-03 07:23:281998 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:241999 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:182000 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:062001 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502002 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082003 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062004 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502005 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082006 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062007 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502008 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082009 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:182010
[email protected]26385172013-05-09 23:11:352011 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182012
2013 error_descriptions = []
2014 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:282015 error_subjects = set()
2016 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:182017 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2018 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:082019 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182020 description_with_path = '%s\n %s' % (path, rule_description)
2021 if rule_type == Rule.DISALLOW:
2022 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282023 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:182024 else:
2025 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282026 warning_subjects.add("#includes")
2027
2028 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2029 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:082030 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:282031 description_with_path = '%s\n %s' % (path, rule_description)
2032 if rule_type == Rule.DISALLOW:
2033 error_descriptions.append(description_with_path)
2034 error_subjects.add("imports")
2035 else:
2036 warning_descriptions.append(description_with_path)
2037 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:182038
Jinsuk Kim5a092672017-10-24 22:42:242039 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:022040 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:082041 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:242042 description_with_path = '%s\n %s' % (path, rule_description)
2043 if rule_type == Rule.DISALLOW:
2044 error_descriptions.append(description_with_path)
2045 error_subjects.add("imports")
2046 else:
2047 warning_descriptions.append(description_with_path)
2048 warning_subjects.add("imports")
2049
[email protected]55f9f382012-07-31 11:02:182050 results = []
2051 if error_descriptions:
2052 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:282053 'You added one or more %s that violate checkdeps rules.'
2054 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:182055 error_descriptions))
2056 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:422057 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:282058 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:182059 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:282060 '%s? See relevant DEPS file(s) for details and contacts.' %
2061 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:182062 warning_descriptions))
2063 return results
2064
2065
[email protected]fbcafe5a2012-08-08 15:31:222066def _CheckFilePermissions(input_api, output_api):
2067 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:152068 if input_api.platform == 'win32':
2069 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:292070 checkperms_tool = input_api.os_path.join(
2071 input_api.PresubmitLocalPath(),
2072 'tools', 'checkperms', 'checkperms.py')
2073 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:472074 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:392075 with input_api.CreateTemporaryFile() as file_list:
2076 for f in input_api.AffectedFiles():
2077 # checkperms.py file/directory arguments must be relative to the
2078 # repository.
2079 file_list.write(f.LocalPath() + '\n')
2080 file_list.close()
2081 args += ['--file-list', file_list.name]
2082 try:
2083 input_api.subprocess.check_output(args)
2084 return []
2085 except input_api.subprocess.CalledProcessError as error:
2086 return [output_api.PresubmitError(
2087 'checkperms.py failed:',
2088 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:222089
2090
robertocn832f5992017-01-04 19:01:302091def _CheckTeamTags(input_api, output_api):
2092 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
2093 checkteamtags_tool = input_api.os_path.join(
2094 input_api.PresubmitLocalPath(),
2095 'tools', 'checkteamtags', 'checkteamtags.py')
2096 args = [input_api.python_executable, checkteamtags_tool,
2097 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:222098 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:302099 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
2100 'OWNERS']
2101 try:
2102 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:052103 warnings = input_api.subprocess.check_output(args + files).splitlines()
2104 if warnings:
2105 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:302106 return []
2107 except input_api.subprocess.CalledProcessError as error:
2108 return [output_api.PresubmitError(
2109 'checkteamtags.py failed:',
2110 long_text=error.output)]
2111
2112
[email protected]c8278b32012-10-30 20:35:492113def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
2114 """Makes sure we don't include ui/aura/window_property.h
2115 in header files.
2116 """
2117 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
2118 errors = []
2119 for f in input_api.AffectedFiles():
2120 if not f.LocalPath().endswith('.h'):
2121 continue
2122 for line_num, line in f.ChangedContents():
2123 if pattern.match(line):
2124 errors.append(' %s:%d' % (f.LocalPath(), line_num))
2125
2126 results = []
2127 if errors:
2128 results.append(output_api.PresubmitError(
2129 'Header files should not include ui/aura/window_property.h', errors))
2130 return results
2131
2132
[email protected]70ca77752012-11-20 03:45:032133def _CheckForVersionControlConflictsInFile(input_api, f):
2134 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
2135 errors = []
2136 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:162137 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:232138 # First-level headers in markdown look a lot like version control
2139 # conflict markers. http://daringfireball.net/projects/markdown/basics
2140 continue
[email protected]70ca77752012-11-20 03:45:032141 if pattern.match(line):
2142 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2143 return errors
2144
2145
2146def _CheckForVersionControlConflicts(input_api, output_api):
2147 """Usually this is not intentional and will cause a compile failure."""
2148 errors = []
2149 for f in input_api.AffectedFiles():
2150 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
2151
2152 results = []
2153 if errors:
2154 results.append(output_api.PresubmitError(
2155 'Version control conflict markers found, please resolve.', errors))
2156 return results
2157
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:202158
estadee17314a02017-01-12 16:22:162159def _CheckGoogleSupportAnswerUrl(input_api, output_api):
2160 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2161 errors = []
2162 for f in input_api.AffectedFiles():
2163 for line_num, line in f.ChangedContents():
2164 if pattern.search(line):
2165 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2166
2167 results = []
2168 if errors:
2169 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502170 'Found Google support URL addressed by answer number. Please replace '
2171 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162172 return results
2173
[email protected]70ca77752012-11-20 03:45:032174
[email protected]06e6d0ff2012-12-11 01:36:442175def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2176 def FilterFile(affected_file):
2177 """Filter function for use with input_api.AffectedSourceFiles,
2178 below. This filters out everything except non-test files from
2179 top-level directories that generally speaking should not hard-code
2180 service URLs (e.g. src/android_webview/, src/content/ and others).
2181 """
2182 return input_api.FilterSourceFile(
2183 affected_file,
Egor Paskoce145c42018-09-28 19:31:042184 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442185 black_list=(_EXCLUDED_PATHS +
2186 _TEST_CODE_EXCLUDED_PATHS +
2187 input_api.DEFAULT_BLACK_LIST))
2188
reillyi38965732015-11-16 18:27:332189 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2190 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462191 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2192 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442193 problems = [] # items are (filename, line_number, line)
2194 for f in input_api.AffectedSourceFiles(FilterFile):
2195 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462196 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442197 problems.append((f.LocalPath(), line_num, line))
2198
2199 if problems:
[email protected]f7051d52013-04-02 18:31:422200 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442201 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582202 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442203 [' %s:%d: %s' % (
2204 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032205 else:
2206 return []
[email protected]06e6d0ff2012-12-11 01:36:442207
2208
James Cook6b6597c2019-11-06 22:05:292209def _CheckChromeOsSyncedPrefRegistration(input_api, output_api):
2210 """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
2211 def FileFilter(affected_file):
2212 """Includes directories known to be Chrome OS only."""
2213 return input_api.FilterSourceFile(
2214 affected_file,
2215 white_list=('^ash/',
2216 '^chromeos/', # Top-level src/chromeos.
2217 '/chromeos/', # Any path component.
2218 '^components/arc',
2219 '^components/exo'),
2220 black_list=(input_api.DEFAULT_BLACK_LIST))
2221
2222 prefs = []
2223 priority_prefs = []
2224 for f in input_api.AffectedFiles(file_filter=FileFilter):
2225 for line_num, line in f.ChangedContents():
2226 if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF', line):
2227 prefs.append(' %s:%d:' % (f.LocalPath(), line_num))
2228 prefs.append(' %s' % line)
2229 if input_api.re.search(
2230 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
2231 priority_prefs.append(' %s:%d' % (f.LocalPath(), line_num))
2232 priority_prefs.append(' %s' % line)
2233
2234 results = []
2235 if (prefs):
2236 results.append(output_api.PresubmitPromptWarning(
2237 'Preferences were registered as SYNCABLE_PREF and will be controlled '
2238 'by browser sync settings. If these prefs should be controlled by OS '
2239 'sync settings use SYNCABLE_OS_PREF instead.\n' + '\n'.join(prefs)))
2240 if (priority_prefs):
2241 results.append(output_api.PresubmitPromptWarning(
2242 'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
2243 'controlled by browser sync settings. If these prefs should be '
2244 'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
2245 'instead.\n' + '\n'.join(prefs)))
2246 return results
2247
2248
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492249# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272250def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2251 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312252 The native_client_sdk directory is excluded because it has auto-generated PNG
2253 files for documentation.
[email protected]d2530012013-01-25 16:39:272254 """
[email protected]d2530012013-01-25 16:39:272255 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492256 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042257 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312258 file_filter = lambda f: input_api.FilterSourceFile(
2259 f, white_list=white_list, black_list=black_list)
2260 for f in input_api.AffectedFiles(include_deletes=False,
2261 file_filter=file_filter):
2262 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272263
2264 results = []
2265 if errors:
2266 results.append(output_api.PresubmitError(
2267 'The name of PNG files should not have abbreviations. \n'
2268 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2269 'Contact [email protected] if you have questions.', errors))
2270 return results
2271
2272
Daniel Cheng4dcdb6b2017-04-13 08:30:172273def _ExtractAddRulesFromParsedDeps(parsed_deps):
2274 """Extract the rules that add dependencies from a parsed DEPS file.
2275
2276 Args:
2277 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2278 add_rules = set()
2279 add_rules.update([
2280 rule[1:] for rule in parsed_deps.get('include_rules', [])
2281 if rule.startswith('+') or rule.startswith('!')
2282 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502283 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172284 {}).iteritems():
2285 add_rules.update([
2286 rule[1:] for rule in rules
2287 if rule.startswith('+') or rule.startswith('!')
2288 ])
2289 return add_rules
2290
2291
2292def _ParseDeps(contents):
2293 """Simple helper for parsing DEPS files."""
2294 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172295 class _VarImpl:
2296
2297 def __init__(self, local_scope):
2298 self._local_scope = local_scope
2299
2300 def Lookup(self, var_name):
2301 """Implements the Var syntax."""
2302 try:
2303 return self._local_scope['vars'][var_name]
2304 except KeyError:
2305 raise Exception('Var is not defined: %s' % var_name)
2306
2307 local_scope = {}
2308 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172309 'Var': _VarImpl(local_scope).Lookup,
2310 }
2311 exec contents in global_scope, local_scope
2312 return local_scope
2313
2314
2315def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082316 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412317 a set of DEPS entries that we should look up.
2318
2319 For a directory (rather than a specific filename) we fake a path to
2320 a specific filename by adding /DEPS. This is chosen as a file that
2321 will seldom or never be subject to per-file include_rules.
2322 """
[email protected]2b438d62013-11-14 17:54:142323 # We ignore deps entries on auto-generated directories.
2324 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082325
Daniel Cheng4dcdb6b2017-04-13 08:30:172326 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2327 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2328
2329 added_deps = new_deps.difference(old_deps)
2330
[email protected]2b438d62013-11-14 17:54:142331 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172332 for added_dep in added_deps:
2333 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2334 continue
2335 # Assume that a rule that ends in .h is a rule for a specific file.
2336 if added_dep.endswith('.h'):
2337 results.add(added_dep)
2338 else:
2339 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082340 return results
2341
2342
[email protected]e871964c2013-05-13 14:14:552343def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2344 """When a dependency prefixed with + is added to a DEPS file, we
2345 want to make sure that the change is reviewed by an OWNER of the
2346 target file or directory, to avoid layering violations from being
2347 introduced. This check verifies that this happens.
2348 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172349 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242350
2351 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492352 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242353 for f in input_api.AffectedFiles(include_deletes=False,
2354 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552355 filename = input_api.os_path.basename(f.LocalPath())
2356 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172357 virtual_depended_on_files.update(_CalculateAddedDeps(
2358 input_api.os_path,
2359 '\n'.join(f.OldContents()),
2360 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552361
[email protected]e871964c2013-05-13 14:14:552362 if not virtual_depended_on_files:
2363 return []
2364
2365 if input_api.is_committing:
2366 if input_api.tbr:
2367 return [output_api.PresubmitNotifyResult(
2368 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272369 if input_api.dry_run:
2370 return [output_api.PresubmitNotifyResult(
2371 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552372 if not input_api.change.issue:
2373 return [output_api.PresubmitError(
2374 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402375 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552376 output = output_api.PresubmitError
2377 else:
2378 output = output_api.PresubmitNotifyResult
2379
2380 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502381 owner_email, reviewers = (
2382 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2383 input_api,
2384 owners_db.email_regexp,
2385 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552386
2387 owner_email = owner_email or input_api.change.author_email
2388
[email protected]de4f7d22013-05-23 14:27:462389 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512390 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462391 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552392 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2393 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412394
2395 # We strip the /DEPS part that was added by
2396 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2397 # directory.
2398 def StripDeps(path):
2399 start_deps = path.rfind('/DEPS')
2400 if start_deps != -1:
2401 return path[:start_deps]
2402 else:
2403 return path
2404 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552405 for path in missing_files]
2406
2407 if unapproved_dependencies:
2408 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152409 output('You need LGTM from owners of depends-on paths in DEPS that were '
2410 'modified in this CL:\n %s' %
2411 '\n '.join(sorted(unapproved_dependencies)))]
2412 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2413 output_list.append(output(
2414 'Suggested missing target path OWNERS:\n %s' %
2415 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552416 return output_list
2417
2418 return []
2419
2420
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492421# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402422def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492423 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402424 black_list = (_EXCLUDED_PATHS +
2425 _TEST_CODE_EXCLUDED_PATHS +
2426 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042427 (r"^base[\\/]logging\.h$",
2428 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222429 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042430 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2431 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2432 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122433 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182434 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152435 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032436 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152437 r"^chrome[\\/]chrome_cleaner[\\/].*",
2438 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2439 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042440 r"^chromecast[\\/]",
2441 r"^cloud_print[\\/]",
2442 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482443 r"dump_stability_report_main_win.cc$",
Egor Paskoce145c42018-09-28 19:31:042444 r"^components[\\/]html_viewer[\\/]"
jochen34415e52015-07-10 08:34:312445 r"web_test_delegate_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042446 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462447 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042448 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462449 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042450 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252451 r"gl_helper_benchmark\.cc$",
Egor Paskoce145c42018-09-28 19:31:042452 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2453 r"^courgette[\\/]courgette_tool\.cc$",
2454 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272455 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Wezd39b367f2019-11-05 00:37:002456 r"^fuchsia[\\/]engine[\\/]context_provider_main.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332457 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042458 r"^ipc[\\/]ipc_logging\.cc$",
2459 r"^native_client_sdk[\\/]",
2460 r"^remoting[\\/]base[\\/]logging\.h$",
2461 r"^remoting[\\/]host[\\/].*",
2462 r"^sandbox[\\/]linux[\\/].*",
DongJun Kimfebb3c22019-10-21 02:08:062463 r"^storage[\\/]browser[\\/]file_system[\\/]" +
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332464 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042465 r"^tools[\\/]",
2466 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2467 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332468 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402469 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492470 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402471
thomasanderson625d3932017-03-29 07:16:582472 log_info = set([])
2473 printf = set([])
[email protected]85218562013-11-22 07:41:402474
2475 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582476 for _, line in f.ChangedContents():
2477 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2478 log_info.add(f.LocalPath())
2479 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2480 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372481
thomasanderson625d3932017-03-29 07:16:582482 if input_api.re.search(r"\bprintf\(", line):
2483 printf.add(f.LocalPath())
2484 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2485 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402486
2487 if log_info:
2488 return [output_api.PresubmitError(
2489 'These files spam the console log with LOG(INFO):',
2490 items=log_info)]
2491 if printf:
2492 return [output_api.PresubmitError(
2493 'These files spam the console log with printf/fprintf:',
2494 items=printf)]
2495 return []
2496
2497
[email protected]49aa76a2013-12-04 06:59:162498def _CheckForAnonymousVariables(input_api, output_api):
2499 """These types are all expected to hold locks while in scope and
2500 so should never be anonymous (which causes them to be immediately
2501 destroyed)."""
2502 they_who_must_be_named = [
2503 'base::AutoLock',
2504 'base::AutoReset',
2505 'base::AutoUnlock',
2506 'SkAutoAlphaRestore',
2507 'SkAutoBitmapShaderInstall',
2508 'SkAutoBlitterChoose',
2509 'SkAutoBounderCommit',
2510 'SkAutoCallProc',
2511 'SkAutoCanvasRestore',
2512 'SkAutoCommentBlock',
2513 'SkAutoDescriptor',
2514 'SkAutoDisableDirectionCheck',
2515 'SkAutoDisableOvalCheck',
2516 'SkAutoFree',
2517 'SkAutoGlyphCache',
2518 'SkAutoHDC',
2519 'SkAutoLockColors',
2520 'SkAutoLockPixels',
2521 'SkAutoMalloc',
2522 'SkAutoMaskFreeImage',
2523 'SkAutoMutexAcquire',
2524 'SkAutoPathBoundsUpdate',
2525 'SkAutoPDFRelease',
2526 'SkAutoRasterClipValidate',
2527 'SkAutoRef',
2528 'SkAutoTime',
2529 'SkAutoTrace',
2530 'SkAutoUnref',
2531 ]
2532 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2533 # bad: base::AutoLock(lock.get());
2534 # not bad: base::AutoLock lock(lock.get());
2535 bad_pattern = input_api.re.compile(anonymous)
2536 # good: new base::AutoLock(lock.get())
2537 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2538 errors = []
2539
2540 for f in input_api.AffectedFiles():
2541 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2542 continue
2543 for linenum, line in f.ChangedContents():
2544 if bad_pattern.search(line) and not good_pattern.search(line):
2545 errors.append('%s:%d' % (f.LocalPath(), linenum))
2546
2547 if errors:
2548 return [output_api.PresubmitError(
2549 'These lines create anonymous variables that need to be named:',
2550 items=errors)]
2551 return []
2552
2553
Peter Kasting4844e46e2018-02-23 07:27:102554def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532555 # Returns whether |template_str| is of the form <T, U...> for some types T
2556 # and U. Assumes that |template_str| is already in the form <...>.
2557 def HasMoreThanOneArg(template_str):
2558 # Level of <...> nesting.
2559 nesting = 0
2560 for c in template_str:
2561 if c == '<':
2562 nesting += 1
2563 elif c == '>':
2564 nesting -= 1
2565 elif c == ',' and nesting == 1:
2566 return True
2567 return False
2568
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492569 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102570 sources = lambda affected_file: input_api.FilterSourceFile(
2571 affected_file,
2572 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2573 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492574 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552575
2576 # Pattern to capture a single "<...>" block of template arguments. It can
2577 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2578 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2579 # latter would likely require counting that < and > match, which is not
2580 # expressible in regular languages. Should the need arise, one can introduce
2581 # limited counting (matching up to a total number of nesting depth), which
2582 # should cover all practical cases for already a low nesting limit.
2583 template_arg_pattern = (
2584 r'<[^>]*' # Opening block of <.
2585 r'>([^<]*>)?') # Closing block of >.
2586 # Prefix expressing that whatever follows is not already inside a <...>
2587 # block.
2588 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102589 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552590 not_inside_template_arg_pattern
2591 + r'\bstd::unique_ptr'
2592 + template_arg_pattern
2593 + r'\(\)')
2594
2595 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2596 template_arg_no_array_pattern = (
2597 r'<[^>]*[^]]' # Opening block of <.
2598 r'>([^(<]*[^]]>)?') # Closing block of >.
2599 # Prefix saying that what follows is the start of an expression.
2600 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2601 # Suffix saying that what follows are call parentheses with a non-empty list
2602 # of arguments.
2603 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532604 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552605 return_construct_pattern = input_api.re.compile(
2606 start_of_expr_pattern
2607 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532608 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552609 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532610 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552611 + nonempty_arg_list_pattern)
2612
Vaclav Brozek851d9602018-04-04 16:13:052613 problems_constructor = []
2614 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102615 for f in input_api.AffectedSourceFiles(sources):
2616 for line_number, line in f.ChangedContents():
2617 # Disallow:
2618 # return std::unique_ptr<T>(foo);
2619 # bar = std::unique_ptr<T>(foo);
2620 # But allow:
2621 # return std::unique_ptr<T[]>(foo);
2622 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532623 # And also allow cases when the second template argument is present. Those
2624 # cases cannot be handled by std::make_unique:
2625 # return std::unique_ptr<T, U>(foo);
2626 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052627 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532628 return_construct_result = return_construct_pattern.search(line)
2629 if return_construct_result and not HasMoreThanOneArg(
2630 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052631 problems_constructor.append(
2632 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102633 # Disallow:
2634 # std::unique_ptr<T>()
2635 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052636 problems_nullptr.append(
2637 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2638
2639 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162640 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052641 errors.append(output_api.PresubmitError(
2642 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162643 problems_nullptr))
2644 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052645 errors.append(output_api.PresubmitError(
2646 'The following files use explicit std::unique_ptr constructor.'
2647 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162648 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102649 return errors
2650
2651
[email protected]999261d2014-03-03 20:08:082652def _CheckUserActionUpdate(input_api, output_api):
2653 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522654 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082655 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522656 # If actions.xml is already included in the changelist, the PRESUBMIT
2657 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082658 return []
2659
[email protected]999261d2014-03-03 20:08:082660 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2661 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522662 current_actions = None
[email protected]999261d2014-03-03 20:08:082663 for f in input_api.AffectedFiles(file_filter=file_filter):
2664 for line_num, line in f.ChangedContents():
2665 match = input_api.re.search(action_re, line)
2666 if match:
[email protected]2f92dec2014-03-07 19:21:522667 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2668 # loaded only once.
2669 if not current_actions:
2670 with open('tools/metrics/actions/actions.xml') as actions_f:
2671 current_actions = actions_f.read()
2672 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082673 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522674 action = 'name="{0}"'.format(action_name)
2675 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082676 return [output_api.PresubmitPromptWarning(
2677 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522678 'tools/metrics/actions/actions.xml. Please run '
2679 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082680 % (f.LocalPath(), line_num, action_name))]
2681 return []
2682
2683
Daniel Cheng13ca61a882017-08-25 15:11:252684def _ImportJSONCommentEater(input_api):
2685 import sys
2686 sys.path = sys.path + [input_api.os_path.join(
2687 input_api.PresubmitLocalPath(),
2688 'tools', 'json_comment_eater')]
2689 import json_comment_eater
2690 return json_comment_eater
2691
2692
[email protected]99171a92014-06-03 08:44:472693def _GetJSONParseError(input_api, filename, eat_comments=True):
2694 try:
2695 contents = input_api.ReadFile(filename)
2696 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252697 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132698 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472699
2700 input_api.json.loads(contents)
2701 except ValueError as e:
2702 return e
2703 return None
2704
2705
2706def _GetIDLParseError(input_api, filename):
2707 try:
2708 contents = input_api.ReadFile(filename)
2709 idl_schema = input_api.os_path.join(
2710 input_api.PresubmitLocalPath(),
2711 'tools', 'json_schema_compiler', 'idl_schema.py')
2712 process = input_api.subprocess.Popen(
2713 [input_api.python_executable, idl_schema],
2714 stdin=input_api.subprocess.PIPE,
2715 stdout=input_api.subprocess.PIPE,
2716 stderr=input_api.subprocess.PIPE,
2717 universal_newlines=True)
2718 (_, error) = process.communicate(input=contents)
2719 return error or None
2720 except ValueError as e:
2721 return e
2722
2723
2724def _CheckParseErrors(input_api, output_api):
2725 """Check that IDL and JSON files do not contain syntax errors."""
2726 actions = {
2727 '.idl': _GetIDLParseError,
2728 '.json': _GetJSONParseError,
2729 }
[email protected]99171a92014-06-03 08:44:472730 # Most JSON files are preprocessed and support comments, but these do not.
2731 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042732 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472733 ]
2734 # Only run IDL checker on files in these directories.
2735 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042736 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2737 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472738 ]
2739
2740 def get_action(affected_file):
2741 filename = affected_file.LocalPath()
2742 return actions.get(input_api.os_path.splitext(filename)[1])
2743
[email protected]99171a92014-06-03 08:44:472744 def FilterFile(affected_file):
2745 action = get_action(affected_file)
2746 if not action:
2747 return False
2748 path = affected_file.LocalPath()
2749
Sean Kau46e29bc2017-08-28 16:31:162750 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472751 return False
2752
2753 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162754 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472755 return False
2756 return True
2757
2758 results = []
2759 for affected_file in input_api.AffectedFiles(
2760 file_filter=FilterFile, include_deletes=False):
2761 action = get_action(affected_file)
2762 kwargs = {}
2763 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162764 _MatchesFile(input_api, json_no_comments_patterns,
2765 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472766 kwargs['eat_comments'] = False
2767 parse_error = action(input_api,
2768 affected_file.AbsoluteLocalPath(),
2769 **kwargs)
2770 if parse_error:
2771 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2772 (affected_file.LocalPath(), parse_error)))
2773 return results
2774
2775
[email protected]760deea2013-12-10 19:33:492776def _CheckJavaStyle(input_api, output_api):
2777 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472778 import sys
[email protected]760deea2013-12-10 19:33:492779 original_sys_path = sys.path
2780 try:
2781 sys.path = sys.path + [input_api.os_path.join(
2782 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2783 import checkstyle
2784 finally:
2785 # Restore sys.path to what it was before.
2786 sys.path = original_sys_path
2787
2788 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092789 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512790 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492791
2792
Nate Fischerdfd9812e2019-07-18 22:03:002793def _CheckPythonDevilInit(input_api, output_api):
2794 """Checks to make sure devil is initialized correctly in python scripts."""
2795 script_common_initialize_pattern = input_api.re.compile(
2796 r'script_common\.InitializeEnvironment\(')
2797 devil_env_config_initialize = input_api.re.compile(
2798 r'devil_env\.config\.Initialize\(')
2799
2800 errors = []
2801
2802 sources = lambda affected_file: input_api.FilterSourceFile(
2803 affected_file,
2804 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2805 (r'^build[\\/]android[\\/]devil_chromium\.py',
2806 r'^third_party[\\/].*',)),
2807 white_list=[r'.*\.py$'])
2808
2809 for f in input_api.AffectedSourceFiles(sources):
2810 for line_num, line in f.ChangedContents():
2811 if (script_common_initialize_pattern.search(line) or
2812 devil_env_config_initialize.search(line)):
2813 errors.append("%s:%d" % (f.LocalPath(), line_num))
2814
2815 results = []
2816
2817 if errors:
2818 results.append(output_api.PresubmitError(
2819 'Devil initialization should always be done using '
2820 'devil_chromium.Initialize() in the chromium project, to use better '
2821 'defaults for dependencies (ex. up-to-date version of adb).',
2822 errors))
2823
2824 return results
2825
2826
Sean Kau46e29bc2017-08-28 16:31:162827def _MatchesFile(input_api, patterns, path):
2828 for pattern in patterns:
2829 if input_api.re.search(pattern, path):
2830 return True
2831 return False
2832
2833
Daniel Cheng7052cdf2017-11-21 19:23:292834def _GetOwnersFilesToCheckForIpcOwners(input_api):
2835 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172836
Daniel Cheng7052cdf2017-11-21 19:23:292837 Returns:
2838 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2839 contain to cover IPC-related files with noparent reviewer rules.
2840 """
2841 # Whether or not a file affects IPC is (mostly) determined by a simple list
2842 # of filename patterns.
dchenge07de812016-06-20 19:27:172843 file_patterns = [
palmerb19a0932017-01-24 04:00:312844 # Legacy IPC:
dchenge07de812016-06-20 19:27:172845 '*_messages.cc',
2846 '*_messages*.h',
2847 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312848 # Mojo IPC:
dchenge07de812016-06-20 19:27:172849 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472850 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172851 '*_struct_traits*.*',
2852 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312853 '*.typemap',
2854 # Android native IPC:
2855 '*.aidl',
2856 # Blink uses a different file naming convention:
2857 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472858 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172859 '*StructTraits*.*',
2860 '*TypeConverter*.*',
2861 ]
2862
scottmg7a6ed5ba2016-11-04 18:22:042863 # These third_party directories do not contain IPCs, but contain files
2864 # matching the above patterns, which trigger false positives.
2865 exclude_paths = [
2866 'third_party/crashpad/*',
Raphael Kubo da Costa4a224cf42019-11-19 18:44:162867 'third_party/blink/renderer/platform/bindings/*',
Andres Medinae684cf42018-08-27 18:48:232868 'third_party/protobuf/benchmarks/python/*',
Nico Weberee3dc9b2017-08-31 17:09:292869 'third_party/win_build_output/*',
Dan Harringtonb60e1aa2019-11-20 08:48:542870 'third_party/feed_library/*',
Scott Violet9f82d362019-11-06 21:42:162871 # These files are just used to communicate between class loaders running
2872 # in the same process.
2873 'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
scottmg7a6ed5ba2016-11-04 18:22:042874 ]
2875
dchenge07de812016-06-20 19:27:172876 # Dictionary mapping an OWNERS file path to Patterns.
2877 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2878 # rules ) to a PatternEntry.
2879 # PatternEntry is a dictionary with two keys:
2880 # - 'files': the files that are matched by this pattern
2881 # - 'rules': the per-file rules needed for this pattern
2882 # For example, if we expect OWNERS file to contain rules for *.mojom and
2883 # *_struct_traits*.*, Patterns might look like this:
2884 # {
2885 # '*.mojom': {
2886 # 'files': ...,
2887 # 'rules': [
2888 # 'per-file *.mojom=set noparent',
2889 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2890 # ],
2891 # },
2892 # '*_struct_traits*.*': {
2893 # 'files': ...,
2894 # 'rules': [
2895 # 'per-file *_struct_traits*.*=set noparent',
2896 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2897 # ],
2898 # },
2899 # }
2900 to_check = {}
2901
Daniel Cheng13ca61a882017-08-25 15:11:252902 def AddPatternToCheck(input_file, pattern):
2903 owners_file = input_api.os_path.join(
2904 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2905 if owners_file not in to_check:
2906 to_check[owners_file] = {}
2907 if pattern not in to_check[owners_file]:
2908 to_check[owners_file][pattern] = {
2909 'files': [],
2910 'rules': [
2911 'per-file %s=set noparent' % pattern,
2912 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2913 ]
2914 }
Vaclav Brozekd5de76a2018-03-17 07:57:502915 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252916
dchenge07de812016-06-20 19:27:172917 # Iterate through the affected files to see what we actually need to check
2918 # for. We should only nag patch authors about per-file rules if a file in that
2919 # directory would match that pattern. If a directory only contains *.mojom
2920 # files and no *_messages*.h files, we should only nag about rules for
2921 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252922 for f in input_api.AffectedFiles(include_deletes=False):
2923 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362924 # affected files for .json, .cc, and .h files which look like they contain
2925 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162926 if (f.LocalPath().endswith('.json') and
2927 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2928 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252929 json_comment_eater = _ImportJSONCommentEater(input_api)
2930 mostly_json_lines = '\n'.join(f.NewContents())
2931 # Comments aren't allowed in strict JSON, so filter them out.
2932 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432933 try:
2934 json_content = input_api.json.loads(json_lines)
2935 except:
2936 # There's another PRESUBMIT check that already verifies that JSON files
2937 # are not invalid, so no need to emit another warning here.
2938 continue
Daniel Cheng13ca61a882017-08-25 15:11:252939 if 'interface_provider_specs' in json_content:
2940 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:362941 else:
2942 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2943 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2944 if (manifest_pattern.search(f.LocalPath()) and not
2945 test_manifest_pattern.search(f.LocalPath())):
2946 # We expect all actual service manifest files to contain at least one
2947 # qualified reference to service_manager::Manifest.
2948 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
2949 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172950 for pattern in file_patterns:
2951 if input_api.fnmatch.fnmatch(
2952 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042953 skip = False
2954 for exclude in exclude_paths:
2955 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2956 skip = True
2957 break
2958 if skip:
2959 continue
Daniel Cheng13ca61a882017-08-25 15:11:252960 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:172961 break
2962
Daniel Cheng7052cdf2017-11-21 19:23:292963 return to_check
2964
2965
2966def _CheckIpcOwners(input_api, output_api):
2967 """Checks that affected files involving IPC have an IPC OWNERS rule."""
2968 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
2969
2970 if to_check:
2971 # If there are any OWNERS files to check, there are IPC-related changes in
2972 # this CL. Auto-CC the review list.
2973 output_api.AppendCC('[email protected]')
2974
2975 # Go through the OWNERS files to check, filtering out rules that are already
2976 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:172977 for owners_file, patterns in to_check.iteritems():
2978 try:
2979 with file(owners_file) as f:
2980 lines = set(f.read().splitlines())
2981 for entry in patterns.itervalues():
2982 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
2983 ]
2984 except IOError:
2985 # No OWNERS file, so all the rules are definitely missing.
2986 continue
2987
2988 # All the remaining lines weren't found in OWNERS files, so emit an error.
2989 errors = []
2990 for owners_file, patterns in to_check.iteritems():
2991 missing_lines = []
2992 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:502993 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:172994 missing_lines.extend(entry['rules'])
2995 files.extend([' %s' % f.LocalPath() for f in entry['files']])
2996 if missing_lines:
2997 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:052998 'Because of the presence of files:\n%s\n\n'
2999 '%s needs the following %d lines added:\n\n%s' %
3000 ('\n'.join(files), owners_file, len(missing_lines),
3001 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:173002
3003 results = []
3004 if errors:
vabrf5ce3bf92016-07-11 14:52:413005 if input_api.is_committing:
3006 output = output_api.PresubmitError
3007 else:
3008 output = output_api.PresubmitPromptWarning
3009 results.append(output(
Daniel Cheng52111692017-06-14 08:00:593010 'Found OWNERS files that need to be updated for IPC security ' +
3011 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:173012 long_text='\n\n'.join(errors)))
3013
3014 return results
3015
3016
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263017def _CheckSetNoParent(input_api, output_api):
3018 """Checks that set noparent is only used together with an OWNERS file in
3019 //build/OWNERS.setnoparent (see also
3020 //docs/code_reviews.md#owners-files-details)
3021 """
3022 errors = []
3023
3024 allowed_owners_files_file = 'build/OWNERS.setnoparent'
3025 allowed_owners_files = set()
3026 with open(allowed_owners_files_file, 'r') as f:
3027 for line in f:
3028 line = line.strip()
3029 if not line or line.startswith('#'):
3030 continue
3031 allowed_owners_files.add(line)
3032
3033 per_file_pattern = input_api.re.compile('per-file (.+)=(.+)')
3034
3035 for f in input_api.AffectedFiles(include_deletes=False):
3036 if not f.LocalPath().endswith('OWNERS'):
3037 continue
3038
3039 found_owners_files = set()
3040 found_set_noparent_lines = dict()
3041
3042 # Parse the OWNERS file.
3043 for lineno, line in enumerate(f.NewContents(), 1):
3044 line = line.strip()
3045 if line.startswith('set noparent'):
3046 found_set_noparent_lines[''] = lineno
3047 if line.startswith('file://'):
3048 if line in allowed_owners_files:
3049 found_owners_files.add('')
3050 if line.startswith('per-file'):
3051 match = per_file_pattern.match(line)
3052 if match:
3053 glob = match.group(1).strip()
3054 directive = match.group(2).strip()
3055 if directive == 'set noparent':
3056 found_set_noparent_lines[glob] = lineno
3057 if directive.startswith('file://'):
3058 if directive in allowed_owners_files:
3059 found_owners_files.add(glob)
3060
3061 # Check that every set noparent line has a corresponding file:// line
3062 # listed in build/OWNERS.setnoparent.
3063 for set_noparent_line in found_set_noparent_lines:
3064 if set_noparent_line in found_owners_files:
3065 continue
3066 errors.append(' %s:%d' % (f.LocalPath(),
3067 found_set_noparent_lines[set_noparent_line]))
3068
3069 results = []
3070 if errors:
3071 if input_api.is_committing:
3072 output = output_api.PresubmitError
3073 else:
3074 output = output_api.PresubmitPromptWarning
3075 results.append(output(
3076 'Found the following "set noparent" restrictions in OWNERS files that '
3077 'do not include owners from build/OWNERS.setnoparent:',
3078 long_text='\n\n'.join(errors)))
3079 return results
3080
3081
jbriance9e12f162016-11-25 07:57:503082def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:313083 """Checks that added or removed lines in non third party affected
3084 header files do not lead to new useless class or struct forward
3085 declaration.
jbriance9e12f162016-11-25 07:57:503086 """
3087 results = []
3088 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
3089 input_api.re.MULTILINE)
3090 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
3091 input_api.re.MULTILINE)
3092 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:313093 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:193094 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:493095 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:313096 continue
3097
jbriance9e12f162016-11-25 07:57:503098 if not f.LocalPath().endswith('.h'):
3099 continue
3100
3101 contents = input_api.ReadFile(f)
3102 fwd_decls = input_api.re.findall(class_pattern, contents)
3103 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
3104
3105 useless_fwd_decls = []
3106 for decl in fwd_decls:
3107 count = sum(1 for _ in input_api.re.finditer(
3108 r'\b%s\b' % input_api.re.escape(decl), contents))
3109 if count == 1:
3110 useless_fwd_decls.append(decl)
3111
3112 if not useless_fwd_decls:
3113 continue
3114
3115 for line in f.GenerateScmDiff().splitlines():
3116 if (line.startswith('-') and not line.startswith('--') or
3117 line.startswith('+') and not line.startswith('++')):
3118 for decl in useless_fwd_decls:
3119 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
3120 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:243121 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:503122 (f.LocalPath(), decl)))
3123 useless_fwd_decls.remove(decl)
3124
3125 return results
3126
Jinsong Fan91ebbbd2019-04-16 14:57:173127def _CheckAndroidDebuggableBuild(input_api, output_api):
3128 """Checks that code uses BuildInfo.isDebugAndroid() instead of
3129 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
3130 this is a debuggable build of Android.
3131 """
3132 build_type_check_pattern = input_api.re.compile(
3133 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
3134
3135 errors = []
3136
3137 sources = lambda affected_file: input_api.FilterSourceFile(
3138 affected_file,
3139 black_list=(_EXCLUDED_PATHS +
3140 _TEST_CODE_EXCLUDED_PATHS +
3141 input_api.DEFAULT_BLACK_LIST +
3142 (r"^android_webview[\\/]support_library[\\/]"
3143 "boundary_interfaces[\\/]",
3144 r"^chrome[\\/]android[\\/]webapk[\\/].*",
3145 r'^third_party[\\/].*',
3146 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
3147 r"webview[\\/]chromium[\\/]License.*",)),
3148 white_list=[r'.*\.java$'])
3149
3150 for f in input_api.AffectedSourceFiles(sources):
3151 for line_num, line in f.ChangedContents():
3152 if build_type_check_pattern.search(line):
3153 errors.append("%s:%d" % (f.LocalPath(), line_num))
3154
3155 results = []
3156
3157 if errors:
3158 results.append(output_api.PresubmitPromptWarning(
3159 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
3160 ' Please use BuildInfo.isDebugAndroid() instead.',
3161 errors))
3162
3163 return results
jbriance9e12f162016-11-25 07:57:503164
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493165# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:293166def _CheckAndroidToastUsage(input_api, output_api):
3167 """Checks that code uses org.chromium.ui.widget.Toast instead of
3168 android.widget.Toast (Chromium Toast doesn't force hardware
3169 acceleration on low-end devices, saving memory).
3170 """
3171 toast_import_pattern = input_api.re.compile(
3172 r'^import android\.widget\.Toast;$')
3173
3174 errors = []
3175
3176 sources = lambda affected_file: input_api.FilterSourceFile(
3177 affected_file,
3178 black_list=(_EXCLUDED_PATHS +
3179 _TEST_CODE_EXCLUDED_PATHS +
3180 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043181 (r'^chromecast[\\/].*',
3182 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493183 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:293184
3185 for f in input_api.AffectedSourceFiles(sources):
3186 for line_num, line in f.ChangedContents():
3187 if toast_import_pattern.search(line):
3188 errors.append("%s:%d" % (f.LocalPath(), line_num))
3189
3190 results = []
3191
3192 if errors:
3193 results.append(output_api.PresubmitError(
3194 'android.widget.Toast usage is detected. Android toasts use hardware'
3195 ' acceleration, and can be\ncostly on low-end devices. Please use'
3196 ' org.chromium.ui.widget.Toast instead.\n'
3197 'Contact [email protected] if you have any questions.',
3198 errors))
3199
3200 return results
3201
3202
dgnaa68d5e2015-06-10 10:08:223203def _CheckAndroidCrLogUsage(input_api, output_api):
3204 """Checks that new logs using org.chromium.base.Log:
3205 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:513206 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:223207 """
pkotwicza1dd0b002016-05-16 14:41:043208
torne89540622017-03-24 19:41:303209 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:043210 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:303211 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:043212 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:303213 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:043214 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
3215 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:093216 # The customtabs_benchmark is a small app that does not depend on Chromium
3217 # java pieces.
Egor Paskoce145c42018-09-28 19:31:043218 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:043219 ]
3220
dgnaa68d5e2015-06-10 10:08:223221 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:123222 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
3223 class_in_base_pattern = input_api.re.compile(
3224 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
3225 has_some_log_import_pattern = input_api.re.compile(
3226 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:223227 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:123228 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:223229 log_decl_pattern = input_api.re.compile(
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463230 r'static final String TAG = "(?P<name>(.*))"')
dgnaa68d5e2015-06-10 10:08:223231
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463232 REF_MSG = ('See docs/android_logging.md for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493233 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:043234 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:123235
dgnaa68d5e2015-06-10 10:08:223236 tag_decl_errors = []
3237 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:123238 tag_errors = []
dgn38736db2015-09-18 19:20:513239 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:123240 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:223241
3242 for f in input_api.AffectedSourceFiles(sources):
3243 file_content = input_api.ReadFile(f)
3244 has_modified_logs = False
3245
3246 # Per line checks
dgn87d9fb62015-06-12 09:15:123247 if (cr_log_import_pattern.search(file_content) or
3248 (class_in_base_pattern.search(file_content) and
3249 not has_some_log_import_pattern.search(file_content))):
3250 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:223251 for line_num, line in f.ChangedContents():
3252
3253 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:123254 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:223255 if match:
3256 has_modified_logs = True
3257
3258 # Make sure it uses "TAG"
3259 if not match.group('tag') == 'TAG':
3260 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:123261 else:
3262 # Report non cr Log function calls in changed lines
3263 for line_num, line in f.ChangedContents():
3264 if log_call_pattern.search(line):
3265 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:223266
3267 # Per file checks
3268 if has_modified_logs:
3269 # Make sure the tag is using the "cr" prefix and is not too long
3270 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513271 tag_name = match.group('name') if match else None
3272 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223273 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513274 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223275 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513276 elif '.' in tag_name:
3277 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223278
3279 results = []
3280 if tag_decl_errors:
3281 results.append(output_api.PresubmitPromptWarning(
3282 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513283 '"private static final String TAG = "<package tag>".\n'
3284 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223285 tag_decl_errors))
3286
3287 if tag_length_errors:
3288 results.append(output_api.PresubmitError(
3289 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513290 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223291 tag_length_errors))
3292
3293 if tag_errors:
3294 results.append(output_api.PresubmitPromptWarning(
3295 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3296 tag_errors))
3297
dgn87d9fb62015-06-12 09:15:123298 if util_log_errors:
dgn4401aa52015-04-29 16:26:173299 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123300 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3301 util_log_errors))
3302
dgn38736db2015-09-18 19:20:513303 if tag_with_dot_errors:
3304 results.append(output_api.PresubmitPromptWarning(
3305 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3306 tag_with_dot_errors))
3307
dgn4401aa52015-04-29 16:26:173308 return results
3309
3310
Yoland Yanb92fa522017-08-28 17:37:063311def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3312 """Checks that junit.framework.* is no longer used."""
3313 deprecated_junit_framework_pattern = input_api.re.compile(
3314 r'^import junit\.framework\..*;',
3315 input_api.re.MULTILINE)
3316 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493317 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063318 errors = []
3319 for f in input_api.AffectedFiles(sources):
3320 for line_num, line in f.ChangedContents():
3321 if deprecated_junit_framework_pattern.search(line):
3322 errors.append("%s:%d" % (f.LocalPath(), line_num))
3323
3324 results = []
3325 if errors:
3326 results.append(output_api.PresubmitError(
3327 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3328 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3329 ' if you have any question.', errors))
3330 return results
3331
3332
3333def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3334 """Checks that if new Java test classes have inheritance.
3335 Either the new test class is JUnit3 test or it is a JUnit4 test class
3336 with a base class, either case is undesirable.
3337 """
3338 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3339
3340 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493341 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063342 errors = []
3343 for f in input_api.AffectedFiles(sources):
3344 if not f.OldContents():
3345 class_declaration_start_flag = False
3346 for line_num, line in f.ChangedContents():
3347 if class_declaration_pattern.search(line):
3348 class_declaration_start_flag = True
3349 if class_declaration_start_flag and ' extends ' in line:
3350 errors.append('%s:%d' % (f.LocalPath(), line_num))
3351 if '{' in line:
3352 class_declaration_start_flag = False
3353
3354 results = []
3355 if errors:
3356 results.append(output_api.PresubmitPromptWarning(
3357 'The newly created files include Test classes that inherits from base'
3358 ' class. Please do not use inheritance in JUnit4 tests or add new'
3359 ' JUnit3 tests. Contact [email protected] if you have any'
3360 ' questions.', errors))
3361 return results
3362
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203363
yolandyan45001472016-12-21 21:12:423364def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3365 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3366 deprecated_annotation_import_pattern = input_api.re.compile(
3367 r'^import android\.test\.suitebuilder\.annotation\..*;',
3368 input_api.re.MULTILINE)
3369 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493370 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423371 errors = []
3372 for f in input_api.AffectedFiles(sources):
3373 for line_num, line in f.ChangedContents():
3374 if deprecated_annotation_import_pattern.search(line):
3375 errors.append("%s:%d" % (f.LocalPath(), line_num))
3376
3377 results = []
3378 if errors:
3379 results.append(output_api.PresubmitError(
3380 'Annotations in android.test.suitebuilder.annotation have been'
3381 ' deprecated since API level 24. Please use android.support.test.filters'
3382 ' from //third_party/android_support_test_runner:runner_java instead.'
3383 ' Contact [email protected] if you have any questions.', errors))
3384 return results
3385
3386
agrieve7b6479d82015-10-07 14:24:223387def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3388 """Checks if MDPI assets are placed in a correct directory."""
3389 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3390 ('/res/drawable/' in f.LocalPath() or
3391 '/res/drawable-ldrtl/' in f.LocalPath()))
3392 errors = []
3393 for f in input_api.AffectedFiles(include_deletes=False,
3394 file_filter=file_filter):
3395 errors.append(' %s' % f.LocalPath())
3396
3397 results = []
3398 if errors:
3399 results.append(output_api.PresubmitError(
3400 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3401 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3402 '/res/drawable-ldrtl/.\n'
3403 'Contact [email protected] if you have questions.', errors))
3404 return results
3405
3406
Nate Fischer535972b2017-09-16 01:06:183407def _CheckAndroidWebkitImports(input_api, output_api):
3408 """Checks that code uses org.chromium.base.Callback instead of
Bo Liubfde1c02019-09-24 23:08:353409 android.webview.ValueCallback except in the WebView glue layer
3410 and WebLayer.
Nate Fischer535972b2017-09-16 01:06:183411 """
3412 valuecallback_import_pattern = input_api.re.compile(
3413 r'^import android\.webkit\.ValueCallback;$')
3414
3415 errors = []
3416
3417 sources = lambda affected_file: input_api.FilterSourceFile(
3418 affected_file,
3419 black_list=(_EXCLUDED_PATHS +
3420 _TEST_CODE_EXCLUDED_PATHS +
3421 input_api.DEFAULT_BLACK_LIST +
Bo Liubfde1c02019-09-24 23:08:353422 (r'^android_webview[\\/]glue[\\/].*',
3423 r'^weblayer[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493424 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183425
3426 for f in input_api.AffectedSourceFiles(sources):
3427 for line_num, line in f.ChangedContents():
3428 if valuecallback_import_pattern.search(line):
3429 errors.append("%s:%d" % (f.LocalPath(), line_num))
3430
3431 results = []
3432
3433 if errors:
3434 results.append(output_api.PresubmitError(
3435 'android.webkit.ValueCallback usage is detected outside of the glue'
3436 ' layer. To stay compatible with the support library, android.webkit.*'
3437 ' classes should only be used inside the glue layer and'
3438 ' org.chromium.base.Callback should be used instead.',
3439 errors))
3440
3441 return results
3442
3443
Becky Zhou7c69b50992018-12-10 19:37:573444def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3445 """Checks Android XML styles """
3446 import sys
3447 original_sys_path = sys.path
3448 try:
3449 sys.path = sys.path + [input_api.os_path.join(
3450 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3451 import checkxmlstyle
3452 finally:
3453 # Restore sys.path to what it was before.
3454 sys.path = original_sys_path
3455
3456 if is_check_on_upload:
3457 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3458 else:
3459 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3460
3461
agrievef32bcc72016-04-04 14:57:403462class PydepsChecker(object):
3463 def __init__(self, input_api, pydeps_files):
3464 self._file_cache = {}
3465 self._input_api = input_api
3466 self._pydeps_files = pydeps_files
3467
3468 def _LoadFile(self, path):
3469 """Returns the list of paths within a .pydeps file relative to //."""
3470 if path not in self._file_cache:
3471 with open(path) as f:
3472 self._file_cache[path] = f.read()
3473 return self._file_cache[path]
3474
3475 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3476 """Returns an interable of paths within the .pydep, relativized to //."""
3477 os_path = self._input_api.os_path
3478 pydeps_dir = os_path.dirname(pydeps_path)
3479 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3480 if not l.startswith('*'))
3481 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3482
3483 def _CreateFilesToPydepsMap(self):
3484 """Returns a map of local_path -> list_of_pydeps."""
3485 ret = {}
3486 for pydep_local_path in self._pydeps_files:
3487 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3488 ret.setdefault(path, []).append(pydep_local_path)
3489 return ret
3490
3491 def ComputeAffectedPydeps(self):
3492 """Returns an iterable of .pydeps files that might need regenerating."""
3493 affected_pydeps = set()
3494 file_to_pydeps_map = None
3495 for f in self._input_api.AffectedFiles(include_deletes=True):
3496 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463497 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3498 # subrepositories. We can't figure out which files change, so re-check
3499 # all files.
3500 # Changes to print_python_deps.py affect all .pydeps.
3501 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403502 return self._pydeps_files
3503 elif local_path.endswith('.pydeps'):
3504 if local_path in self._pydeps_files:
3505 affected_pydeps.add(local_path)
3506 elif local_path.endswith('.py'):
3507 if file_to_pydeps_map is None:
3508 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3509 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3510 return affected_pydeps
3511
3512 def DetermineIfStale(self, pydeps_path):
3513 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413514 import difflib
John Budorick47ca3fe2018-02-10 00:53:103515 import os
3516
agrievef32bcc72016-04-04 14:57:403517 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3518 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103519 env = dict(os.environ)
3520 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403521 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103522 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413523 old_contents = old_pydeps_data[2:]
3524 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403525 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413526 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403527
3528
Tibor Goldschwendt360793f72019-06-25 18:23:493529def _ParseGclientArgs():
3530 args = {}
3531 with open('build/config/gclient_args.gni', 'r') as f:
3532 for line in f:
3533 line = line.strip()
3534 if not line or line.startswith('#'):
3535 continue
3536 attribute, value = line.split('=')
3537 args[attribute.strip()] = value.strip()
3538 return args
3539
3540
agrievef32bcc72016-04-04 14:57:403541def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3542 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403543 # This check is for Python dependency lists (.pydeps files), and involves
3544 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3545 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283546 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003547 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493548 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403549 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3550 results = []
3551 # First, check for new / deleted .pydeps.
3552 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033553 # Check whether we are running the presubmit check for a file in src.
3554 # f.LocalPath is relative to repo (src, or internal repo).
3555 # os_path.exists is relative to src repo.
3556 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3557 # to src and we can conclude that the pydeps is in src.
3558 if input_api.os_path.exists(f.LocalPath()):
3559 if f.LocalPath().endswith('.pydeps'):
3560 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3561 results.append(output_api.PresubmitError(
3562 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3563 'remove %s' % f.LocalPath()))
3564 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3565 results.append(output_api.PresubmitError(
3566 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3567 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403568
3569 if results:
3570 return results
3571
3572 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3573
3574 for pydep_path in checker.ComputeAffectedPydeps():
3575 try:
phajdan.jr0d9878552016-11-04 10:49:413576 result = checker.DetermineIfStale(pydep_path)
3577 if result:
3578 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403579 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413580 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3581 'To regenerate, run:\n\n %s' %
3582 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403583 except input_api.subprocess.CalledProcessError as error:
3584 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3585 long_text=error.output)]
3586
3587 return results
3588
3589
glidere61efad2015-02-18 17:39:433590def _CheckSingletonInHeaders(input_api, output_api):
3591 """Checks to make sure no header files have |Singleton<|."""
3592 def FileFilter(affected_file):
3593 # It's ok for base/memory/singleton.h to have |Singleton<|.
3594 black_list = (_EXCLUDED_PATHS +
3595 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043596 (r"^base[\\/]memory[\\/]singleton\.h$",
3597 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473598 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433599 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3600
sergeyu34d21222015-09-16 00:11:443601 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433602 files = []
3603 for f in input_api.AffectedSourceFiles(FileFilter):
3604 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3605 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3606 contents = input_api.ReadFile(f)
3607 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243608 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433609 pattern.search(line)):
3610 files.append(f)
3611 break
3612
3613 if files:
yolandyandaabc6d2016-04-18 18:29:393614 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443615 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433616 'Please move them to an appropriate source file so that the ' +
3617 'template gets instantiated in a single compilation unit.',
3618 files) ]
3619 return []
3620
3621
[email protected]fd20b902014-05-09 02:14:533622_DEPRECATED_CSS = [
3623 # Values
3624 ( "-webkit-box", "flex" ),
3625 ( "-webkit-inline-box", "inline-flex" ),
3626 ( "-webkit-flex", "flex" ),
3627 ( "-webkit-inline-flex", "inline-flex" ),
3628 ( "-webkit-min-content", "min-content" ),
3629 ( "-webkit-max-content", "max-content" ),
3630
3631 # Properties
3632 ( "-webkit-background-clip", "background-clip" ),
3633 ( "-webkit-background-origin", "background-origin" ),
3634 ( "-webkit-background-size", "background-size" ),
3635 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443636 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533637
3638 # Functions
3639 ( "-webkit-gradient", "gradient" ),
3640 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3641 ( "-webkit-linear-gradient", "linear-gradient" ),
3642 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3643 ( "-webkit-radial-gradient", "radial-gradient" ),
3644 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3645]
3646
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203647
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493648# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243649def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533650 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253651 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343652 documentation and iOS CSS for dom distiller
3653 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253654 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533655 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493656 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253657 black_list = (_EXCLUDED_PATHS +
3658 _TEST_CODE_EXCLUDED_PATHS +
3659 input_api.DEFAULT_BLACK_LIST +
3660 (r"^chrome/common/extensions/docs",
3661 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343662 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443663 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253664 r"^native_client_sdk"))
3665 file_filter = lambda f: input_api.FilterSourceFile(
3666 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533667 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3668 for line_num, line in fpath.ChangedContents():
3669 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023670 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533671 results.append(output_api.PresubmitError(
3672 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3673 (fpath.LocalPath(), line_num, deprecated_value, value)))
3674 return results
3675
mohan.reddyf21db962014-10-16 12:26:473676
rlanday6802cf632017-05-30 17:48:363677def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363678 bad_files = {}
3679 for f in input_api.AffectedFiles(include_deletes=False):
3680 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493681 not f.LocalPath().startswith('third_party/blink') and
3682 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363683 continue
3684
Daniel Bratell65b033262019-04-23 08:17:063685 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363686 continue
3687
Vaclav Brozekd5de76a2018-03-17 07:57:503688 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363689 if "#include" in line and "../" in line]
3690 if not relative_includes:
3691 continue
3692 bad_files[f.LocalPath()] = relative_includes
3693
3694 if not bad_files:
3695 return []
3696
3697 error_descriptions = []
3698 for file_path, bad_lines in bad_files.iteritems():
3699 error_description = file_path
3700 for line in bad_lines:
3701 error_description += '\n ' + line
3702 error_descriptions.append(error_description)
3703
3704 results = []
3705 results.append(output_api.PresubmitError(
3706 'You added one or more relative #include paths (including "../").\n'
3707 'These shouldn\'t be used because they can be used to include headers\n'
3708 'from code that\'s not correctly specified as a dependency in the\n'
3709 'relevant BUILD.gn file(s).',
3710 error_descriptions))
3711
3712 return results
3713
Takeshi Yoshinoe387aa32017-08-02 13:16:133714
Daniel Bratell65b033262019-04-23 08:17:063715def _CheckForCcIncludes(input_api, output_api):
3716 """Check that nobody tries to include a cc file. It's a relatively
3717 common error which results in duplicate symbols in object
3718 files. This may not always break the build until someone later gets
3719 very confusing linking errors."""
3720 results = []
3721 for f in input_api.AffectedFiles(include_deletes=False):
3722 # We let third_party code do whatever it wants
3723 if (f.LocalPath().startswith('third_party') and
3724 not f.LocalPath().startswith('third_party/blink') and
3725 not f.LocalPath().startswith('third_party\\blink')):
3726 continue
3727
3728 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3729 continue
3730
3731 for _, line in f.ChangedContents():
3732 if line.startswith('#include "'):
3733 included_file = line.split('"')[1]
3734 if _IsCPlusPlusFile(input_api, included_file):
3735 # The most common naming for external files with C++ code,
3736 # apart from standard headers, is to call them foo.inc, but
3737 # Chromium sometimes uses foo-inc.cc so allow that as well.
3738 if not included_file.endswith(('.h', '-inc.cc')):
3739 results.append(output_api.PresubmitError(
3740 'Only header files or .inc files should be included in other\n'
3741 'C++ files. Compiling the contents of a cc file more than once\n'
3742 'will cause duplicate information in the build which may later\n'
3743 'result in strange link_errors.\n' +
3744 f.LocalPath() + ':\n ' +
3745 line))
3746
3747 return results
3748
3749
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203750def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3751 if not isinstance(key, ast.Str):
3752 return 'Key at line %d must be a string literal' % key.lineno
3753 if not isinstance(value, ast.Dict):
3754 return 'Value at line %d must be a dict' % value.lineno
3755 if len(value.keys) != 1:
3756 return 'Dict at line %d must have single entry' % value.lineno
3757 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3758 return (
3759 'Entry at line %d must have a string literal \'filepath\' as key' %
3760 value.lineno)
3761 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133762
Takeshi Yoshinoe387aa32017-08-02 13:16:133763
Sergey Ulanov4af16052018-11-08 02:41:463764def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203765 if not isinstance(key, ast.Str):
3766 return 'Key at line %d must be a string literal' % key.lineno
3767 if not isinstance(value, ast.List):
3768 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463769 for element in value.elts:
3770 if not isinstance(element, ast.Str):
3771 return 'Watchlist elements on line %d is not a string' % key.lineno
3772 if not email_regex.match(element.s):
3773 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3774 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203775 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133776
Takeshi Yoshinoe387aa32017-08-02 13:16:133777
Sergey Ulanov4af16052018-11-08 02:41:463778def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203779 mismatch_template = (
3780 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3781 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133782
Sergey Ulanov4af16052018-11-08 02:41:463783 email_regex = input_api.re.compile(
3784 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3785
3786 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203787 i = 0
3788 last_key = ''
3789 while True:
3790 if i >= len(wd_dict.keys):
3791 if i >= len(w_dict.keys):
3792 return None
3793 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3794 elif i >= len(w_dict.keys):
3795 return (
3796 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133797
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203798 wd_key = wd_dict.keys[i]
3799 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133800
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203801 result = _CheckWatchlistDefinitionsEntrySyntax(
3802 wd_key, wd_dict.values[i], ast)
3803 if result is not None:
3804 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133805
Sergey Ulanov4af16052018-11-08 02:41:463806 result = _CheckWatchlistsEntrySyntax(
3807 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203808 if result is not None:
3809 return 'Bad entry in WATCHLISTS dict: %s' % result
3810
3811 if wd_key.s != w_key.s:
3812 return mismatch_template % (
3813 '%s at line %d' % (wd_key.s, wd_key.lineno),
3814 '%s at line %d' % (w_key.s, w_key.lineno))
3815
3816 if wd_key.s < last_key:
3817 return (
3818 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3819 (wd_key.lineno, w_key.lineno))
3820 last_key = wd_key.s
3821
3822 i = i + 1
3823
3824
Sergey Ulanov4af16052018-11-08 02:41:463825def _CheckWATCHLISTSSyntax(expression, input_api):
3826 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203827 if not isinstance(expression, ast.Expression):
3828 return 'WATCHLISTS file must contain a valid expression'
3829 dictionary = expression.body
3830 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3831 return 'WATCHLISTS file must have single dict with exactly two entries'
3832
3833 first_key = dictionary.keys[0]
3834 first_value = dictionary.values[0]
3835 second_key = dictionary.keys[1]
3836 second_value = dictionary.values[1]
3837
3838 if (not isinstance(first_key, ast.Str) or
3839 first_key.s != 'WATCHLIST_DEFINITIONS' or
3840 not isinstance(first_value, ast.Dict)):
3841 return (
3842 'The first entry of the dict in WATCHLISTS file must be '
3843 'WATCHLIST_DEFINITIONS dict')
3844
3845 if (not isinstance(second_key, ast.Str) or
3846 second_key.s != 'WATCHLISTS' or
3847 not isinstance(second_value, ast.Dict)):
3848 return (
3849 'The second entry of the dict in WATCHLISTS file must be '
3850 'WATCHLISTS dict')
3851
Sergey Ulanov4af16052018-11-08 02:41:463852 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133853
3854
3855def _CheckWATCHLISTS(input_api, output_api):
3856 for f in input_api.AffectedFiles(include_deletes=False):
3857 if f.LocalPath() == 'WATCHLISTS':
3858 contents = input_api.ReadFile(f, 'r')
3859
3860 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203861 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133862 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203863 # Get an AST tree for it and scan the tree for detailed style checking.
3864 expression = input_api.ast.parse(
3865 contents, filename='WATCHLISTS', mode='eval')
3866 except ValueError as e:
3867 return [output_api.PresubmitError(
3868 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3869 except SyntaxError as e:
3870 return [output_api.PresubmitError(
3871 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3872 except TypeError as e:
3873 return [output_api.PresubmitError(
3874 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133875
Sergey Ulanov4af16052018-11-08 02:41:463876 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203877 if result is not None:
3878 return [output_api.PresubmitError(result)]
3879 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133880
3881 return []
3882
3883
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193884def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3885 """Checks that newly added header files have corresponding GN changes.
3886 Note that this is only a heuristic. To be precise, run script:
3887 build/check_gn_headers.py.
3888 """
3889
3890 def headers(f):
3891 return input_api.FilterSourceFile(
3892 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3893
3894 new_headers = []
3895 for f in input_api.AffectedSourceFiles(headers):
3896 if f.Action() != 'A':
3897 continue
3898 new_headers.append(f.LocalPath())
3899
3900 def gn_files(f):
3901 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3902
3903 all_gn_changed_contents = ''
3904 for f in input_api.AffectedSourceFiles(gn_files):
3905 for _, line in f.ChangedContents():
3906 all_gn_changed_contents += line
3907
3908 problems = []
3909 for header in new_headers:
3910 basename = input_api.os_path.basename(header)
3911 if basename not in all_gn_changed_contents:
3912 problems.append(header)
3913
3914 if problems:
3915 return [output_api.PresubmitPromptWarning(
3916 'Missing GN changes for new header files', items=sorted(problems),
3917 long_text='Please double check whether newly added header files need '
3918 'corresponding changes in gn or gni files.\nThis checking is only a '
3919 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3920 'Read https://crbug.com/661774 for more info.')]
3921 return []
3922
3923
Michael Giuffridad3bc8672018-10-25 22:48:023924def _CheckCorrectProductNameInMessages(input_api, output_api):
3925 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3926
3927 This assumes we won't intentionally reference one product from the other
3928 product.
3929 """
3930 all_problems = []
3931 test_cases = [{
3932 "filename_postfix": "google_chrome_strings.grd",
3933 "correct_name": "Chrome",
3934 "incorrect_name": "Chromium",
3935 }, {
3936 "filename_postfix": "chromium_strings.grd",
3937 "correct_name": "Chromium",
3938 "incorrect_name": "Chrome",
3939 }]
3940
3941 for test_case in test_cases:
3942 problems = []
3943 filename_filter = lambda x: x.LocalPath().endswith(
3944 test_case["filename_postfix"])
3945
3946 # Check each new line. Can yield false positives in multiline comments, but
3947 # easier than trying to parse the XML because messages can have nested
3948 # children, and associating message elements with affected lines is hard.
3949 for f in input_api.AffectedSourceFiles(filename_filter):
3950 for line_num, line in f.ChangedContents():
3951 if "<message" in line or "<!--" in line or "-->" in line:
3952 continue
3953 if test_case["incorrect_name"] in line:
3954 problems.append(
3955 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
3956
3957 if problems:
3958 message = (
3959 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
3960 % (test_case["correct_name"], test_case["correct_name"],
3961 test_case["incorrect_name"]))
3962 all_problems.append(
3963 output_api.PresubmitPromptWarning(message, items=problems))
3964
3965 return all_problems
3966
3967
Dirk Pranke3c18a382019-03-15 01:07:513968def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
3969 # TODO(crbug.com/941824): We need to make sure the entries in
3970 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3971 # so that users of //buildtools in other projects get the same tooling
3972 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3973 # support to gclient, we can eliminate the duplication and delete
3974 # this presubmit check.
3975
3976 # Update this regexp if new revisions are added to the files.
3977 rev_regexp = input_api.re.compile(
Dirk Pranke6d095b42019-03-15 23:44:013978 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:513979
3980 # If a user is changing one revision, they need to change the same
3981 # line in both files. This means that any given change should contain
3982 # exactly the same list of changed lines that match the regexps. The
3983 # replace(' ', '') call allows us to ignore whitespace changes to the
3984 # lines. The 'long_text' parameter to the error will contain the
3985 # list of changed lines in both files, which should make it easy enough
3986 # to spot the error without going overboard in this implementation.
3987 revs_changes = {
3988 'DEPS': {},
3989 'buildtools/DEPS': {},
3990 }
3991 long_text = ''
3992
3993 for f in input_api.AffectedFiles(
3994 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
3995 for line_num, line in f.ChangedContents():
3996 if rev_regexp.search(line):
3997 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
3998 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
3999
4000 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
4001 return [output_api.PresubmitError(
4002 'Change buildtools revisions in sync in both //DEPS and '
4003 '//buildtools/DEPS.', long_text=long_text + '\n')]
4004 else:
4005 return []
4006
4007
Daniel Bratell93eb6c62019-04-29 20:13:364008def _CheckForTooLargeFiles(input_api, output_api):
4009 """Avoid large files, especially binary files, in the repository since
4010 git doesn't scale well for those. They will be in everyone's repo
4011 clones forever, forever making Chromium slower to clone and work
4012 with."""
4013
4014 # Uploading files to cloud storage is not trivial so we don't want
4015 # to set the limit too low, but the upper limit for "normal" large
4016 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
4017 # anything over 20 MB is exceptional.
4018 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
4019
4020 too_large_files = []
4021 for f in input_api.AffectedFiles():
4022 # Check both added and modified files (but not deleted files).
4023 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:384024 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:364025 if size > TOO_LARGE_FILE_SIZE_LIMIT:
4026 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
4027
4028 if too_large_files:
4029 message = (
4030 'Do not commit large files to git since git scales badly for those.\n' +
4031 'Instead put the large files in cloud storage and use DEPS to\n' +
4032 'fetch them.\n' + '\n'.join(too_large_files)
4033 )
4034 return [output_api.PresubmitError(
4035 'Too large files found in commit', long_text=message + '\n')]
4036 else:
4037 return []
4038
Max Morozb47503b2019-08-08 21:03:274039
4040def _CheckFuzzTargets(input_api, output_api):
4041 """Checks specific for fuzz target sources."""
4042 EXPORTED_SYMBOLS = [
4043 'LLVMFuzzerInitialize',
4044 'LLVMFuzzerCustomMutator',
4045 'LLVMFuzzerCustomCrossOver',
4046 'LLVMFuzzerMutate',
4047 ]
4048
4049 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
4050
4051 def FilterFile(affected_file):
4052 """Ignore libFuzzer source code."""
4053 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
4054 black_list = r"^third_party[\\/]libFuzzer"
4055
4056 return input_api.FilterSourceFile(
4057 affected_file,
4058 white_list=[white_list],
4059 black_list=[black_list])
4060
4061 files_with_missing_header = []
4062 for f in input_api.AffectedSourceFiles(FilterFile):
4063 contents = input_api.ReadFile(f, 'r')
4064 if REQUIRED_HEADER in contents:
4065 continue
4066
4067 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
4068 files_with_missing_header.append(f.LocalPath())
4069
4070 if not files_with_missing_header:
4071 return []
4072
4073 long_text = (
4074 'If you define any of the libFuzzer optional functions (%s), it is '
4075 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
4076 'work incorrectly on Mac (crbug.com/687076).\nNote that '
4077 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
4078 'to access command line arguments passed to the fuzzer. Instead, prefer '
4079 'static initialization and shared resources as documented in '
4080 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
4081 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
4082 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
4083 )
4084
4085 return [output_api.PresubmitPromptWarning(
4086 message="Missing '%s' in:" % REQUIRED_HEADER,
4087 items=files_with_missing_header,
4088 long_text=long_text)]
4089
4090
Mohamed Heikald048240a2019-11-12 16:57:374091def _CheckNewImagesWarning(input_api, output_api):
4092 """
4093 Warns authors who add images into the repo to make sure their images are
4094 optimized before committing.
4095 """
4096 images_added = False
4097 image_paths = []
4098 errors = []
4099 filter_lambda = lambda x: input_api.FilterSourceFile(
4100 x,
4101 black_list=(('(?i).*test', r'.*\/junit\/')
4102 + input_api.DEFAULT_BLACK_LIST),
4103 white_list=[r'.*\/(drawable|mipmap)' ]
4104 )
4105 for f in input_api.AffectedFiles(
4106 include_deletes=False, file_filter=filter_lambda):
4107 local_path = f.LocalPath().lower()
4108 if any(local_path.endswith(extension) for extension in _IMAGE_EXTENSIONS):
4109 images_added = True
4110 image_paths.append(f)
4111 if images_added:
4112 errors.append(output_api.PresubmitPromptWarning(
4113 'It looks like you are trying to commit some images. If these are '
4114 'non-test-only images, please make sure to read and apply the tips in '
4115 'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
4116 'binary_size/optimization_advice.md#optimizing-images\nThis check is '
4117 'FYI only and will not block your CL on the CQ.', image_paths))
4118 return errors
4119
4120
dgnaa68d5e2015-06-10 10:08:224121def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:574122 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:224123 results = []
dgnaa68d5e2015-06-10 10:08:224124 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:174125 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:224126 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:294127 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:064128 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
4129 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:424130 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:184131 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574132 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
Mohamed Heikald048240a2019-11-12 16:57:374133 results.extend(_CheckNewImagesWarning(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574134 return results
4135
4136def _AndroidSpecificOnCommitChecks(input_api, output_api):
4137 """Groups commit checks that target android code."""
4138 results = []
4139 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:224140 return results
4141
4142
[email protected]22c9bd72011-03-27 16:47:394143def _CommonChecks(input_api, output_api):
4144 """Checks common to both upload and commit."""
4145 results = []
4146 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:384147 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:544148 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:084149
4150 author = input_api.change.author_email
4151 if author and author not in _KNOWN_ROBOTS:
4152 results.extend(
4153 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
4154
[email protected]55459852011-08-10 15:17:194155 results.extend(
[email protected]760deea2013-12-10 19:33:494156 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:234157 results.extend(
4158 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:544159 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:184160 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:344161 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:524162 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:224163 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:444164 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:594165 results.extend(_CheckNoBannedFunctions(input_api, output_api))
Mario Sanchez Prada2472cab2019-09-18 10:58:314166 results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:064167 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:124168 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:184169 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:224170 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:304171 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:494172 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:034173 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:494174 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:444175 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
James Cook6b6597c2019-11-06 22:05:294176 results.extend(_CheckChromeOsSyncedPrefRegistration(input_api, output_api))
[email protected]d2530012013-01-25 16:39:274177 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:074178 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:544179 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:444180 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:394181 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:554182 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:044183 results.extend(
4184 input_api.canned_checks.CheckChangeHasNoTabs(
4185 input_api,
4186 output_api,
4187 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:404188 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:164189 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:084190 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:244191 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:474192 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:044193 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:054194 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:144195 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:234196 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:434197 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:404198 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:154199 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:174200 results.extend(_CheckIpcOwners(input_api, output_api))
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264201 results.extend(_CheckSetNoParent(input_api, output_api))
jbriance9e12f162016-11-25 07:57:504202 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:364203 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:064204 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:134205 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:434206 results.extend(input_api.RunTests(
4207 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144208 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:024209 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:514210 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:364211 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:004212 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:244213
Vaclav Brozekcdc7defb2018-03-20 09:54:354214 for f in input_api.AffectedFiles():
4215 path, name = input_api.os_path.split(f.LocalPath())
4216 if name == 'PRESUBMIT.py':
4217 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:004218 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
4219 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:074220 # The PRESUBMIT.py file (and the directory containing it) might
4221 # have been affected by being moved or removed, so only try to
4222 # run the tests if they still exist.
4223 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
4224 input_api, output_api, full_path,
4225 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:394226 return results
[email protected]1f7b4172010-01-28 01:17:344227
[email protected]b337cb5b2011-01-23 21:24:054228
[email protected]b8079ae4a2012-12-05 19:56:494229def _CheckPatchFiles(input_api, output_api):
4230 problems = [f.LocalPath() for f in input_api.AffectedFiles()
4231 if f.LocalPath().endswith(('.orig', '.rej'))]
4232 if problems:
4233 return [output_api.PresubmitError(
4234 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:034235 else:
4236 return []
[email protected]b8079ae4a2012-12-05 19:56:494237
4238
Kent Tamura5a8755d2017-06-29 23:37:074239def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:214240 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
4241 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
4242 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:074243 include_re = input_api.re.compile(
4244 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
4245 extension_re = input_api.re.compile(r'\.[a-z]+$')
4246 errors = []
4247 for f in input_api.AffectedFiles():
4248 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
4249 continue
4250 found_line_number = None
4251 found_macro = None
4252 for line_num, line in f.ChangedContents():
4253 match = macro_re.search(line)
4254 if match:
4255 found_line_number = line_num
4256 found_macro = match.group(2)
4257 break
4258 if not found_line_number:
4259 continue
4260
4261 found_include = False
4262 for line in f.NewContents():
4263 if include_re.search(line):
4264 found_include = True
4265 break
4266 if found_include:
4267 continue
4268
4269 if not f.LocalPath().endswith('.h'):
4270 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
4271 try:
4272 content = input_api.ReadFile(primary_header_path, 'r')
4273 if include_re.search(content):
4274 continue
4275 except IOError:
4276 pass
4277 errors.append('%s:%d %s macro is used without including build/'
4278 'build_config.h.'
4279 % (f.LocalPath(), found_line_number, found_macro))
4280 if errors:
4281 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
4282 return []
4283
4284
[email protected]b00342e7f2013-03-26 16:21:544285def _DidYouMeanOSMacro(bad_macro):
4286 try:
4287 return {'A': 'OS_ANDROID',
4288 'B': 'OS_BSD',
4289 'C': 'OS_CHROMEOS',
4290 'F': 'OS_FREEBSD',
4291 'L': 'OS_LINUX',
4292 'M': 'OS_MACOSX',
4293 'N': 'OS_NACL',
4294 'O': 'OS_OPENBSD',
4295 'P': 'OS_POSIX',
4296 'S': 'OS_SOLARIS',
4297 'W': 'OS_WIN'}[bad_macro[3].upper()]
4298 except KeyError:
4299 return ''
4300
4301
4302def _CheckForInvalidOSMacrosInFile(input_api, f):
4303 """Check for sensible looking, totally invalid OS macros."""
4304 preprocessor_statement = input_api.re.compile(r'^\s*#')
4305 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4306 results = []
4307 for lnum, line in f.ChangedContents():
4308 if preprocessor_statement.search(line):
4309 for match in os_macro.finditer(line):
4310 if not match.group(1) in _VALID_OS_MACROS:
4311 good = _DidYouMeanOSMacro(match.group(1))
4312 did_you_mean = ' (did you mean %s?)' % good if good else ''
4313 results.append(' %s:%d %s%s' % (f.LocalPath(),
4314 lnum,
4315 match.group(1),
4316 did_you_mean))
4317 return results
4318
4319
4320def _CheckForInvalidOSMacros(input_api, output_api):
4321 """Check all affected files for invalid OS macros."""
4322 bad_macros = []
tzik3f295992018-12-04 20:32:234323 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474324 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544325 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4326
4327 if not bad_macros:
4328 return []
4329
4330 return [output_api.PresubmitError(
4331 'Possibly invalid OS macro[s] found. Please fix your code\n'
4332 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4333
lliabraa35bab3932014-10-01 12:16:444334
4335def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4336 """Check all affected files for invalid "if defined" macros."""
4337 ALWAYS_DEFINED_MACROS = (
4338 "TARGET_CPU_PPC",
4339 "TARGET_CPU_PPC64",
4340 "TARGET_CPU_68K",
4341 "TARGET_CPU_X86",
4342 "TARGET_CPU_ARM",
4343 "TARGET_CPU_MIPS",
4344 "TARGET_CPU_SPARC",
4345 "TARGET_CPU_ALPHA",
4346 "TARGET_IPHONE_SIMULATOR",
4347 "TARGET_OS_EMBEDDED",
4348 "TARGET_OS_IPHONE",
4349 "TARGET_OS_MAC",
4350 "TARGET_OS_UNIX",
4351 "TARGET_OS_WIN32",
4352 )
4353 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4354 results = []
4355 for lnum, line in f.ChangedContents():
4356 for match in ifdef_macro.finditer(line):
4357 if match.group(1) in ALWAYS_DEFINED_MACROS:
4358 always_defined = ' %s is always defined. ' % match.group(1)
4359 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4360 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4361 lnum,
4362 always_defined,
4363 did_you_mean))
4364 return results
4365
4366
4367def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4368 """Check all affected files for invalid "if defined" macros."""
4369 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054370 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444371 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054372 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214373 continue
lliabraa35bab3932014-10-01 12:16:444374 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4375 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4376
4377 if not bad_macros:
4378 return []
4379
4380 return [output_api.PresubmitError(
4381 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4382 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4383 bad_macros)]
4384
4385
mlamouria82272622014-09-16 18:45:044386def _CheckForIPCRules(input_api, output_api):
4387 """Check for same IPC rules described in
4388 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4389 """
4390 base_pattern = r'IPC_ENUM_TRAITS\('
4391 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4392 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4393
4394 problems = []
4395 for f in input_api.AffectedSourceFiles(None):
4396 local_path = f.LocalPath()
4397 if not local_path.endswith('.h'):
4398 continue
4399 for line_number, line in f.ChangedContents():
4400 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4401 problems.append(
4402 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4403
4404 if problems:
4405 return [output_api.PresubmitPromptWarning(
4406 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4407 else:
4408 return []
4409
[email protected]b00342e7f2013-03-26 16:21:544410
Stephen Martinis97a394142018-06-07 23:06:054411def _CheckForLongPathnames(input_api, output_api):
4412 """Check to make sure no files being submitted have long paths.
4413 This causes issues on Windows.
4414 """
4415 problems = []
Stephen Martinisc4b246b2019-10-31 23:04:194416 for f in input_api.AffectedTestableFiles():
Stephen Martinis97a394142018-06-07 23:06:054417 local_path = f.LocalPath()
4418 # Windows has a path limit of 260 characters. Limit path length to 200 so
4419 # that we have some extra for the prefix on dev machines and the bots.
4420 if len(local_path) > 200:
4421 problems.append(local_path)
4422
4423 if problems:
4424 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4425 else:
4426 return []
4427
4428
Daniel Bratell8ba52722018-03-02 16:06:144429def _CheckForIncludeGuards(input_api, output_api):
4430 """Check that header files have proper guards against multiple inclusion.
4431 If a file should not have such guards (and it probably should) then it
4432 should include the string "no-include-guard-because-multiply-included".
4433 """
Daniel Bratell6a75baef62018-06-04 10:04:454434 def is_chromium_header_file(f):
4435 # We only check header files under the control of the Chromium
4436 # project. That is, those outside third_party apart from
4437 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324438 # We also exclude *_message_generator.h headers as they use
4439 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454440 file_with_path = input_api.os_path.normpath(f.LocalPath())
4441 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324442 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454443 (not file_with_path.startswith('third_party') or
4444 file_with_path.startswith(
4445 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144446
4447 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344448 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144449
4450 errors = []
4451
Daniel Bratell6a75baef62018-06-04 10:04:454452 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144453 guard_name = None
4454 guard_line_number = None
4455 seen_guard_end = False
4456
4457 file_with_path = input_api.os_path.normpath(f.LocalPath())
4458 base_file_name = input_api.os_path.splitext(
4459 input_api.os_path.basename(file_with_path))[0]
4460 upper_base_file_name = base_file_name.upper()
4461
4462 expected_guard = replace_special_with_underscore(
4463 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144464
4465 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574466 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4467 # are too many (1000+) files with slight deviations from the
4468 # coding style. The most important part is that the include guard
4469 # is there, and that it's unique, not the name so this check is
4470 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144471 #
4472 # As code becomes more uniform, this could be made stricter.
4473
4474 guard_name_pattern_list = [
4475 # Anything with the right suffix (maybe with an extra _).
4476 r'\w+_H__?',
4477
Daniel Bratell39b5b062018-05-16 18:09:574478 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144479 r'\w+_h',
4480
4481 # Anything including the uppercase name of the file.
4482 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4483 upper_base_file_name)) + r'\w*',
4484 ]
4485 guard_name_pattern = '|'.join(guard_name_pattern_list)
4486 guard_pattern = input_api.re.compile(
4487 r'#ifndef\s+(' + guard_name_pattern + ')')
4488
4489 for line_number, line in enumerate(f.NewContents()):
4490 if 'no-include-guard-because-multiply-included' in line:
4491 guard_name = 'DUMMY' # To not trigger check outside the loop.
4492 break
4493
4494 if guard_name is None:
4495 match = guard_pattern.match(line)
4496 if match:
4497 guard_name = match.group(1)
4498 guard_line_number = line_number
4499
Daniel Bratell39b5b062018-05-16 18:09:574500 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454501 # don't match the chromium style guide, but new files should
4502 # get it right.
4503 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574504 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144505 errors.append(output_api.PresubmitPromptWarning(
4506 'Header using the wrong include guard name %s' % guard_name,
4507 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Istiaque Ahmed9ad6cd22019-10-04 00:26:574508 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144509 else:
4510 # The line after #ifndef should have a #define of the same name.
4511 if line_number == guard_line_number + 1:
4512 expected_line = '#define %s' % guard_name
4513 if line != expected_line:
4514 errors.append(output_api.PresubmitPromptWarning(
4515 'Missing "%s" for include guard' % expected_line,
4516 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4517 'Expected: %r\nGot: %r' % (expected_line, line)))
4518
4519 if not seen_guard_end and line == '#endif // %s' % guard_name:
4520 seen_guard_end = True
4521 elif seen_guard_end:
4522 if line.strip() != '':
4523 errors.append(output_api.PresubmitPromptWarning(
4524 'Include guard %s not covering the whole file' % (
4525 guard_name), [f.LocalPath()]))
4526 break # Nothing else to check and enough to warn once.
4527
4528 if guard_name is None:
4529 errors.append(output_api.PresubmitPromptWarning(
4530 'Missing include guard %s' % expected_guard,
4531 [f.LocalPath()],
4532 'Missing include guard in %s\n'
4533 'Recommended name: %s\n'
4534 'This check can be disabled by having the string\n'
4535 'no-include-guard-because-multiply-included in the header.' %
4536 (f.LocalPath(), expected_guard)))
4537
4538 return errors
4539
4540
mostynbb639aca52015-01-07 20:31:234541def _CheckForWindowsLineEndings(input_api, output_api):
4542 """Check source code and known ascii text files for Windows style line
4543 endings.
4544 """
earthdok1b5e0ee2015-03-10 15:19:104545 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234546
4547 file_inclusion_pattern = (
4548 known_text_files,
4549 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4550 )
4551
mostynbb639aca52015-01-07 20:31:234552 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534553 source_file_filter = lambda f: input_api.FilterSourceFile(
4554 f, white_list=file_inclusion_pattern, black_list=None)
4555 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504556 include_file = False
4557 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234558 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504559 include_file = True
4560 if include_file:
4561 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234562
4563 if problems:
4564 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4565 'these files to contain Windows style line endings?\n' +
4566 '\n'.join(problems))]
4567
4568 return []
4569
4570
Vaclav Brozekd5de76a2018-03-17 07:57:504571def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134572 """Checks that all source files use SYSLOG properly."""
4573 syslog_files = []
4574 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564575 for line_number, line in f.ChangedContents():
4576 if 'SYSLOG' in line:
4577 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4578
pastarmovj89f7ee12016-09-20 14:58:134579 if syslog_files:
4580 return [output_api.PresubmitPromptWarning(
4581 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4582 ' calls.\nFiles to check:\n', items=syslog_files)]
4583 return []
4584
4585
[email protected]1f7b4172010-01-28 01:17:344586def CheckChangeOnUpload(input_api, output_api):
4587 results = []
4588 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474589 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284590 results.extend(
jam93a6ee792017-02-08 23:59:224591 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194592 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224593 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134594 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164595 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534596 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194597 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274598 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544599 return results
[email protected]ca8d1982009-02-19 16:33:124600
4601
[email protected]1bfb8322014-04-23 01:02:414602def GetTryServerMasterForBot(bot):
4603 """Returns the Try Server master for the given bot.
4604
[email protected]0bb112362014-07-26 04:38:324605 It tries to guess the master from the bot name, but may still fail
4606 and return None. There is no longer a default master.
4607 """
4608 # Potentially ambiguous bot names are listed explicitly.
4609 master_map = {
tandriie5587792016-07-14 00:34:504610 'chromium_presubmit': 'master.tryserver.chromium.linux',
4611 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414612 }
[email protected]0bb112362014-07-26 04:38:324613 master = master_map.get(bot)
4614 if not master:
wnwen4fbaab82016-05-25 12:54:364615 if 'android' in bot:
tandriie5587792016-07-14 00:34:504616 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364617 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504618 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324619 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504620 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324621 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504622 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324623 return master
[email protected]1bfb8322014-04-23 01:02:414624
4625
[email protected]ca8d1982009-02-19 16:33:124626def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544627 results = []
[email protected]1f7b4172010-01-28 01:17:344628 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574629 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544630 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274631 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344632 input_api,
4633 output_api,
[email protected]2fdd1f362013-01-16 03:56:034634 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274635
jam93a6ee792017-02-08 23:59:224636 results.extend(
4637 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544638 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4639 input_api, output_api))
Dan Beam39f28cb2019-10-04 01:01:384640 results.extend(input_api.canned_checks.CheckChangeHasNoUnwantedTags(
4641 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414642 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4643 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544644 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144645
4646
4647def _CheckTranslationScreenshots(input_api, output_api):
Mustafa Emre Acerad8fb082019-11-19 04:24:214648 PART_FILE_TAG = "part"
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144649 import os
4650 import sys
4651 from io import StringIO
4652
4653 try:
4654 old_sys_path = sys.path
4655 sys.path = sys.path + [input_api.os_path.join(
Mustafa Emre Acerad8fb082019-11-19 04:24:214656 input_api.PresubmitLocalPath(), 'tools', 'grit')]
4657 import grit.grd_reader
4658 import grit.node.message
4659 import grit.util
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144660 finally:
4661 sys.path = old_sys_path
4662
Mustafa Emre Acerad8fb082019-11-19 04:24:214663 def _GetGrdMessages(grd_path_or_string, dir_path='.'):
4664 """Load the grd file and return a dict of message ids to messages.
4665
4666 Ignores any nested grdp files pointed by <part> tag.
4667 """
4668 doc = grit.grd_reader.Parse(grd_path_or_string, dir_path,
4669 stop_after=None, first_ids_file=None,
4670 debug=False, defines={'_chromium': 1},
4671 tags_to_ignore=set([PART_FILE_TAG]))
4672 return {
4673 msg.attrs['name']:msg for msg in doc.GetChildrenOfType(
4674 grit.node.message.MessageNode)
4675 }
4676
4677 def _GetGrdpMessagesFromString(grdp_string):
4678 """Parses the contents of a grdp file given in grdp_string.
4679
4680 grd_reader can't parse grdp files directly. Instead, this creates a
4681 temporary directory with a grd file pointing to the grdp file, and loads the
4682 grd from there. Any nested grdp files (pointed by <part> tag) are ignored.
4683 """
4684 WRAPPER = """<?xml version="1.0" encoding="utf-8"?>
4685 <grit latest_public_release="1" current_release="1">
4686 <release seq="1">
4687 <messages>
4688 <part file="sub.grdp" />
4689 </messages>
4690 </release>
4691 </grit>
4692 """
4693 with grit.util.TempDir({'main.grd': WRAPPER,
4694 'sub.grdp': grdp_string}) as temp_dir:
4695 return _GetGrdMessages(temp_dir.GetPath('main.grd'), temp_dir.GetPath())
4696
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144697 new_or_added_paths = set(f.LocalPath()
4698 for f in input_api.AffectedFiles()
4699 if (f.Action() == 'A' or f.Action() == 'M'))
4700 removed_paths = set(f.LocalPath()
4701 for f in input_api.AffectedFiles(include_deletes=True)
4702 if f.Action() == 'D')
4703
4704 affected_grds = [f for f in input_api.AffectedFiles()
4705 if (f.LocalPath().endswith('.grd') or
4706 f.LocalPath().endswith('.grdp'))]
4707 affected_png_paths = [f.AbsoluteLocalPath()
4708 for f in input_api.AffectedFiles()
4709 if (f.LocalPath().endswith('.png'))]
4710
4711 # Check for screenshots. Developers can upload screenshots using
4712 # tools/translation/upload_screenshots.py which finds and uploads
4713 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4714 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4715 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4716 #
4717 # The logic here is as follows:
4718 #
4719 # - If the CL has a .png file under the screenshots directory for a grd
4720 # file, warn the developer. Actual images should never be checked into the
4721 # Chrome repo.
4722 #
4723 # - If the CL contains modified or new messages in grd files and doesn't
4724 # contain the corresponding .sha1 files, warn the developer to add images
4725 # and upload them via tools/translation/upload_screenshots.py.
4726 #
4727 # - If the CL contains modified or new messages in grd files and the
4728 # corresponding .sha1 files, everything looks good.
4729 #
4730 # - If the CL contains removed messages in grd files but the corresponding
4731 # .sha1 files aren't removed, warn the developer to remove them.
4732 unnecessary_screenshots = []
4733 missing_sha1 = []
4734 unnecessary_sha1_files = []
4735
4736
4737 def _CheckScreenshotAdded(screenshots_dir, message_id):
4738 sha1_path = input_api.os_path.join(
4739 screenshots_dir, message_id + '.png.sha1')
4740 if sha1_path not in new_or_added_paths:
4741 missing_sha1.append(sha1_path)
4742
4743
4744 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4745 sha1_path = input_api.os_path.join(
4746 screenshots_dir, message_id + '.png.sha1')
meacere7be7532019-10-02 17:41:034747 if input_api.os_path.exists(sha1_path) and sha1_path not in removed_paths:
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144748 unnecessary_sha1_files.append(sha1_path)
4749
4750
4751 for f in affected_grds:
4752 file_path = f.LocalPath()
4753 old_id_to_msg_map = {}
4754 new_id_to_msg_map = {}
4755 if file_path.endswith('.grdp'):
4756 if f.OldContents():
Mustafa Emre Acerad8fb082019-11-19 04:24:214757 old_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394758 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144759 if f.NewContents():
Mustafa Emre Acerad8fb082019-11-19 04:24:214760 new_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394761 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144762 else:
4763 if f.OldContents():
Mustafa Emre Acerad8fb082019-11-19 04:24:214764 old_id_to_msg_map = _GetGrdMessages(
4765 StringIO(unicode('\n'.join(f.OldContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144766 if f.NewContents():
Mustafa Emre Acerad8fb082019-11-19 04:24:214767 new_id_to_msg_map = _GetGrdMessages(
4768 StringIO(unicode('\n'.join(f.NewContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144769
4770 # Compute added, removed and modified message IDs.
4771 old_ids = set(old_id_to_msg_map)
4772 new_ids = set(new_id_to_msg_map)
4773 added_ids = new_ids - old_ids
4774 removed_ids = old_ids - new_ids
4775 modified_ids = set([])
4776 for key in old_ids.intersection(new_ids):
4777 if (old_id_to_msg_map[key].FormatXml()
4778 != new_id_to_msg_map[key].FormatXml()):
4779 modified_ids.add(key)
4780
4781 grd_name, ext = input_api.os_path.splitext(
4782 input_api.os_path.basename(file_path))
4783 screenshots_dir = input_api.os_path.join(
4784 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4785
4786 # Check the screenshot directory for .png files. Warn if there is any.
4787 for png_path in affected_png_paths:
4788 if png_path.startswith(screenshots_dir):
4789 unnecessary_screenshots.append(png_path)
4790
4791 for added_id in added_ids:
4792 _CheckScreenshotAdded(screenshots_dir, added_id)
4793
4794 for modified_id in modified_ids:
4795 _CheckScreenshotAdded(screenshots_dir, modified_id)
4796
4797 for removed_id in removed_ids:
4798 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4799
4800 results = []
4801 if unnecessary_screenshots:
4802 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394803 'Do not include actual screenshots in the changelist. Run '
4804 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144805 sorted(unnecessary_screenshots)))
4806
4807 if missing_sha1:
4808 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394809 'You are adding or modifying UI strings.\n'
4810 'To ensure the best translations, take screenshots of the relevant UI '
4811 '(https://g.co/chrome/translation) and add these files to your '
4812 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144813
4814 if unnecessary_sha1_files:
4815 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394816 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144817 sorted(unnecessary_sha1_files)))
4818
4819 return results