blob: 8d6e62647b3350fcd6a0509811ce4357b1911536 [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 = (
[email protected]40d1dbb2012-10-26 07:18:0013 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
14 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2815 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0816 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5417 r"^skia[\\\/].*",
Kent Tamurae9b3a9ec2017-08-31 02:20:1918 r"^third_party[\\\/](WebKit|blink)[\\\/].*",
Mark Mentovaiebb9ddd62017-09-25 17:24:4119 r"^third_party[\\\/]breakpad[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
vapierb2053f542017-03-09 19:46:1026 r"tools[\\\/]md_browser[\\\/].*\.css$",
Kenneth Russell077c8d92017-12-16 02:52:1427 # Test pages for Maps telemetry tests.
28 r"tools[\\\/]perf[\\\/]page_sets[\\\/]maps_perf_test.*",
ehmaldonado78eee2ed2017-03-28 13:16:5429 # Test pages for WebRTC telemetry tests.
30 r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4031)
[email protected]ca8d1982009-02-19 16:33:1232
wnwenbdc444e2016-05-25 13:44:1533
[email protected]06e6d0ff2012-12-11 01:36:4434# Fragment of a regular expression that matches C++ and Objective-C++
35# implementation files.
36_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
37
wnwenbdc444e2016-05-25 13:44:1538
[email protected]06e6d0ff2012-12-11 01:36:4439# Regular expression that matches code only used for test binaries
40# (best effort).
41_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4942 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4443 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
Steven Holte27008b7422018-01-29 20:55:4444 r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1245 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4446 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0548 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4949 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4750 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4951 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0852 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4953 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4454)
[email protected]ca8d1982009-02-19 16:33:1255
wnwenbdc444e2016-05-25 13:44:1556
[email protected]eea609a2011-11-18 13:10:1257_TEST_ONLY_WARNING = (
58 'You might be calling functions intended only for testing from\n'
59 'production code. It is OK to ignore this warning if you know what\n'
60 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5861 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1262
63
[email protected]cf9b78f2012-11-14 11:40:2864_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4065 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2166 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
67 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2868
wnwenbdc444e2016-05-25 13:44:1569
Eric Stevensona9a980972017-09-23 00:04:4170_BANNED_JAVA_FUNCTIONS = (
71 (
72 'StrictMode.allowThreadDiskReads()',
73 (
74 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
75 'directly.',
76 ),
77 False,
78 ),
79 (
80 'StrictMode.allowThreadDiskWrites()',
81 (
82 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
83 'directly.',
84 ),
85 False,
86 ),
87)
88
[email protected]127f18ec2012-06-16 05:05:5989_BANNED_OBJC_FUNCTIONS = (
90 (
91 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2092 (
93 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5994 'prohibited. Please use CrTrackingArea instead.',
95 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
96 ),
97 False,
98 ),
99 (
[email protected]eaae1972014-04-16 04:17:26100 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20101 (
102 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59103 'instead.',
104 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
105 ),
106 False,
107 ),
108 (
109 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20110 (
111 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59112 'Please use |convertPoint:(point) fromView:nil| instead.',
113 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
114 ),
115 True,
116 ),
117 (
118 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20119 (
120 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59121 'Please use |convertPoint:(point) toView:nil| instead.',
122 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
123 ),
124 True,
125 ),
126 (
127 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20128 (
129 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59130 'Please use |convertRect:(point) fromView:nil| instead.',
131 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
132 ),
133 True,
134 ),
135 (
136 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20137 (
138 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59139 'Please use |convertRect:(point) toView:nil| instead.',
140 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
141 ),
142 True,
143 ),
144 (
145 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20146 (
147 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59148 'Please use |convertSize:(point) fromView:nil| instead.',
149 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
150 ),
151 True,
152 ),
153 (
154 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20155 (
156 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59157 'Please use |convertSize:(point) toView:nil| instead.',
158 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
159 ),
160 True,
161 ),
jif65398702016-10-27 10:19:48162 (
163 r"/\s+UTF8String\s*]",
164 (
165 'The use of -[NSString UTF8String] is dangerous as it can return null',
166 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
167 'Please use |SysNSStringToUTF8| instead.',
168 ),
169 True,
170 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34171 (
172 r'__unsafe_unretained',
173 (
174 'The use of __unsafe_unretained is almost certainly wrong, unless',
175 'when interacting with NSFastEnumeration or NSInvocation.',
176 'Please use __weak in files build with ARC, nothing otherwise.',
177 ),
178 False,
179 ),
[email protected]127f18ec2012-06-16 05:05:59180)
181
Sylvain Defresnea8b73d252018-02-28 15:45:54182_BANNED_IOS_OBJC_FUNCTIONS = (
183 (
184 r'/\bTEST[(]',
185 (
186 'TEST() macro should not be used in Objective-C++ code as it does not ',
187 'drain the autorelease pool at the end of the test. Use TEST_F() ',
188 'macro instead with a fixture inheriting from PlatformTest (or a ',
189 'typedef).'
190 ),
191 True,
192 ),
193 (
194 r'/\btesting::Test\b',
195 (
196 'testing::Test should not be used in Objective-C++ code as it does ',
197 'not drain the autorelease pool at the end of the test. Use ',
198 'PlatformTest instead.'
199 ),
200 True,
201 ),
202)
203
[email protected]127f18ec2012-06-16 05:05:59204
205_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20206 # Make sure that gtest's FRIEND_TEST() macro is not used; the
207 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30208 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20209 (
thomasandersone7caaa9b2017-03-29 19:22:53210 r'\bNULL\b',
211 (
212 'New code should not use NULL. Use nullptr instead.',
213 ),
214 True,
215 (),
216 ),
217 (
[email protected]23e6cbc2012-06-16 18:51:20218 'FRIEND_TEST(',
219 (
[email protected]e3c945502012-06-26 20:01:49220 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20221 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
222 ),
223 False,
[email protected]7345da02012-11-27 14:31:49224 (),
[email protected]23e6cbc2012-06-16 18:51:20225 ),
226 (
thomasanderson4b569052016-09-14 20:15:53227 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
228 (
229 'Chrome clients wishing to select events on X windows should use',
230 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
231 'you are selecting events from the GPU process, or if you are using',
232 'an XDisplay other than gfx::GetXDisplay().',
233 ),
234 True,
235 (
236 r"^ui[\\\/]gl[\\\/].*\.cc$",
237 r"^media[\\\/]gpu[\\\/].*\.cc$",
238 r"^gpu[\\\/].*\.cc$",
239 ),
240 ),
241 (
thomasandersone043e3ce2017-06-08 00:43:20242 r'XInternAtom|xcb_intern_atom',
243 (
thomasanderson11aa41d2017-06-08 22:22:38244 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20245 ),
246 True,
247 (
thomasanderson11aa41d2017-06-08 22:22:38248 r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$",
249 r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20250 r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$",
251 ),
252 ),
253 (
tomhudsone2c14d552016-05-26 17:07:46254 'setMatrixClip',
255 (
256 'Overriding setMatrixClip() is prohibited; ',
257 'the base function is deprecated. ',
258 ),
259 True,
260 (),
261 ),
262 (
[email protected]52657f62013-05-20 05:30:31263 'SkRefPtr',
264 (
265 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22266 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31267 ),
268 True,
269 (),
270 ),
271 (
272 'SkAutoRef',
273 (
274 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22275 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31276 ),
277 True,
278 (),
279 ),
280 (
281 'SkAutoTUnref',
282 (
283 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22284 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31285 ),
286 True,
287 (),
288 ),
289 (
290 'SkAutoUnref',
291 (
292 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
293 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22294 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31295 ),
296 True,
297 (),
298 ),
[email protected]d89eec82013-12-03 14:10:59299 (
300 r'/HANDLE_EINTR\(.*close',
301 (
302 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
303 'descriptor will be closed, and it is incorrect to retry the close.',
304 'Either call close directly and ignore its return value, or wrap close',
305 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
306 ),
307 True,
308 (),
309 ),
310 (
311 r'/IGNORE_EINTR\((?!.*close)',
312 (
313 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
314 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
315 ),
316 True,
317 (
318 # Files that #define IGNORE_EINTR.
319 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
320 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
321 ),
322 ),
[email protected]ec5b3f02014-04-04 18:43:43323 (
324 r'/v8::Extension\(',
325 (
326 'Do not introduce new v8::Extensions into the code base, use',
327 'gin::Wrappable instead. See http://crbug.com/334679',
328 ),
329 True,
[email protected]f55c90ee62014-04-12 00:50:03330 (
joaodasilva718f87672014-08-30 09:25:49331 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03332 ),
[email protected]ec5b3f02014-04-04 18:43:43333 ),
skyostilf9469f72015-04-20 10:38:52334 (
jame2d1a952016-04-02 00:27:10335 '#pragma comment(lib,',
336 (
337 'Specify libraries to link with in build files and not in the source.',
338 ),
339 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41340 (
341 r'^third_party[\\\/]abseil-cpp[\\\/].*',
342 ),
jame2d1a952016-04-02 00:27:10343 ),
fdorayc4ac18d2017-05-01 21:39:59344 (
Gabriel Charette7cc6c432018-04-25 20:52:02345 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59346 (
347 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
348 ),
349 False,
350 (),
351 ),
352 (
Gabriel Charette7cc6c432018-04-25 20:52:02353 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59354 (
355 'Consider using THREAD_CHECKER macros instead of the class directly.',
356 ),
357 False,
358 (),
359 ),
dbeamb6f4fde2017-06-15 04:03:06360 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06361 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
362 (
363 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
364 'deprecated (http://crbug.com/634507). Please avoid converting away',
365 'from the Time types in Chromium code, especially if any math is',
366 'being done on time values. For interfacing with platform/library',
367 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
368 'type converter methods instead. For faking TimeXXX values (for unit',
369 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
370 'other use cases, please contact base/time/OWNERS.',
371 ),
372 False,
373 (),
374 ),
375 (
dbeamb6f4fde2017-06-15 04:03:06376 'CallJavascriptFunctionUnsafe',
377 (
378 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
379 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
380 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
381 ),
382 False,
383 (
384 r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$',
385 r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$',
386 r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$',
387 ),
388 ),
dskiba1474c2bfd62017-07-20 02:19:24389 (
390 'leveldb::DB::Open',
391 (
392 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
393 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
394 "Chrome's tracing, making their memory usage visible.",
395 ),
396 True,
397 (
398 r'^third_party/leveldatabase/.*\.(cc|h)$',
399 ),
Gabriel Charette0592c3a2017-07-26 12:02:04400 ),
401 (
Chris Mumfordc38afb62017-10-09 17:55:08402 'leveldb::NewMemEnv',
403 (
404 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58405 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
406 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08407 ),
408 True,
409 (
410 r'^third_party/leveldatabase/.*\.(cc|h)$',
411 ),
412 ),
413 (
Gabriel Charetted9839bc2017-07-29 14:17:47414 'RunLoop::QuitCurrent',
415 (
Robert Liao64b7ab22017-08-04 23:03:43416 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
417 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47418 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41419 False,
Gabriel Charetted9839bc2017-07-29 14:17:47420 (),
Gabriel Charettea44975052017-08-21 23:14:04421 ),
422 (
423 'base::ScopedMockTimeMessageLoopTaskRunner',
424 (
Gabriel Charette87cc1af2018-04-25 20:52:51425 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
426 'ScopedTaskEnvironment::MainThreadType::MOCK_TIME. There are still a',
427 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
428 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
429 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04430 ),
Gabriel Charette87cc1af2018-04-25 20:52:51431 False,
Gabriel Charettea44975052017-08-21 23:14:04432 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57433 ),
434 (
435 r'std::regex',
436 (
437 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02438 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57439 ),
440 True,
441 (),
Francois Doray43670e32017-09-27 12:40:38442 ),
443 (
444 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
445 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
446 (
447 'Use the new API in base/threading/thread_restrictions.h.',
448 ),
449 True,
450 (),
451 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38452 (
453 r'/\bbase::Bind\(',
454 (
Gabriel Charette147335ea2018-03-22 15:59:19455 'Please consider using base::Bind{Once,Repeating} instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02456 'of base::Bind. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38457 ),
458 False,
459 (),
460 ),
461 (
462 r'/\bbase::Callback<',
463 (
Gabriel Charette147335ea2018-03-22 15:59:19464 'Please consider using base::{Once,Repeating}Callback instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02465 'of base::Callback. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38466 ),
467 False,
468 (),
469 ),
470 (
471 r'/\bbase::Closure\b',
472 (
Gabriel Charette147335ea2018-03-22 15:59:19473 'Please consider using base::{Once,Repeating}Closure instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02474 'of base::Closure. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38475 ),
476 False,
477 (),
478 ),
Victor Costan3653df62018-02-08 21:38:16479 (
Gabriel Charette147335ea2018-03-22 15:59:19480 r'RunMessageLoop',
481 (
482 'RunMessageLoop is deprecated, use RunLoop instead.',
483 ),
484 False,
485 (),
486 ),
487 (
488 r'RunThisRunLoop',
489 (
490 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
491 ),
492 False,
493 (),
494 ),
495 (
496 r'RunAllPendingInMessageLoop()',
497 (
498 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
499 "if you're convinced you need this.",
500 ),
501 False,
502 (),
503 ),
504 (
505 r'RunAllPendingInMessageLoop(BrowserThread',
506 (
507 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
508 'BrowserThread::UI, TestBrowserThreadBundle::RunIOThreadUntilIdle',
509 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
510 'async events instead of flushing threads.',
511 ),
512 False,
513 (),
514 ),
515 (
516 r'MessageLoopRunner',
517 (
518 'MessageLoopRunner is deprecated, use RunLoop instead.',
519 ),
520 False,
521 (),
522 ),
523 (
524 r'GetDeferredQuitTaskForRunLoop',
525 (
526 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
527 "gab@ if you found a use case where this is the only solution.",
528 ),
529 False,
530 (),
531 ),
532 (
Victor Costan3653df62018-02-08 21:38:16533 'sqlite3_initialize',
534 (
535 'Instead of sqlite3_initialize, depend on //sql, ',
536 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
537 ),
538 True,
539 (
540 r'^sql/initialization\.(cc|h)$',
541 r'^third_party/sqlite/.*\.(c|cc|h)$',
542 ),
543 ),
Matt Menke7f520a82018-03-28 21:38:37544 (
545 'net::URLFetcher',
546 (
547 'net::URLFetcher should no longer be used in content embedders. ',
548 'Instead, use network::SimpleURLLoader instead, which supports ',
549 'an out-of-process network stack. ',
550 'net::URLFetcher may still be used in binaries that do not embed',
551 'content.',
552 ),
Matt Menke59716d02018-04-05 12:45:53553 False,
Matt Menke7f520a82018-03-28 21:38:37554 (
555 r'^ios[\\\/].*\.(cc|h)$',
556 r'.*[\\\/]ios[\\\/].*\.(cc|h)$',
557 r'.*_ios\.(cc|h)$',
558 r'^net[\\\/].*\.(cc|h)$',
559 r'.*[\\\/]tools[\\\/].*\.(cc|h)$',
560 ),
561 ),
jdoerried7d10ab2018-04-27 10:46:13562 (
563 r'/\barraysize\b',
564 (
565 "arraysize is deprecated, please use base::size(array) instead ",
566 "(https://crbug.com/837308). ",
567 ),
568 False,
569 (),
570 ),
tzik5de2157f2018-05-08 03:42:47571 (
572 r'std::random_shuffle',
573 (
574 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
575 'base::RandomShuffle instead.'
576 ),
577 True,
578 (),
579 ),
[email protected]127f18ec2012-06-16 05:05:59580)
581
wnwenbdc444e2016-05-25 13:44:15582
mlamouria82272622014-09-16 18:45:04583_IPC_ENUM_TRAITS_DEPRECATED = (
584 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50585 'See http://www.chromium.org/Home/chromium-security/education/'
586 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:04587
Stephen Martinis97a394142018-06-07 23:06:05588_LONG_PATH_ERROR = (
589 'Some files included in this CL have file names that are too long (> 200'
590 ' characters). If committed, these files will cause issues on Windows. See'
591 ' https://crbug.com/612667 for more details.'
592)
593
Shenghua Zhangbfaa38b82017-11-16 21:58:02594_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
595 r".*[\\\/]BuildHooksAndroidImpl\.java",
James Wallace-Lee524eb682018-05-10 01:36:35596 r".*[\\\/]ClassRegisterImpl\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:02597 r".*[\\\/]LicenseContentProvider\.java",
James Wallace-Leef31ae6c2018-05-01 23:30:20598 r".*[\\\/]PlatformServiceBridgeImpl.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:02599]
[email protected]127f18ec2012-06-16 05:05:59600
Sean Kau46e29bc2017-08-28 16:31:16601# These paths contain test data and other known invalid JSON files.
602_KNOWN_INVALID_JSON_FILE_PATTERNS = [
603 r'test[\\\/]data[\\\/]',
604 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
605 r'^third_party[\\\/]protobuf[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16606 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Alexey Kozyatinskiya42a629f2018-04-17 17:49:38607 r'^third_party[\\\/]blink[\\\/]renderer[\\\/]devtools[\\\/]protocol\.json$',
Sean Kau46e29bc2017-08-28 16:31:16608]
609
610
[email protected]b00342e7f2013-03-26 16:21:54611_VALID_OS_MACROS = (
612 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08613 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54614 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:12615 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:54616 'OS_BSD',
617 'OS_CAT', # For testing.
618 'OS_CHROMEOS',
619 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37620 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54621 'OS_IOS',
622 'OS_LINUX',
623 'OS_MACOSX',
624 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21625 'OS_NACL_NONSFI',
626 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12627 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54628 'OS_OPENBSD',
629 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37630 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54631 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54632 'OS_WIN',
633)
634
635
agrievef32bcc72016-04-04 14:57:40636_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Grievea7f1ee902018-05-18 16:17:22637 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:40638 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04639 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58640 'build/secondary/third_party/android_platform/'
641 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19642 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40643]
644
wnwenbdc444e2016-05-25 13:44:15645
agrievef32bcc72016-04-04 14:57:40646_GENERIC_PYDEPS_FILES = [
John Chencde89192018-01-27 21:18:40647 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:22648 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:40649]
650
wnwenbdc444e2016-05-25 13:44:15651
agrievef32bcc72016-04-04 14:57:40652_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
653
654
Eric Boren6fd2b932018-01-25 15:05:08655# Bypass the AUTHORS check for these accounts.
656_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:29657 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
658 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
659 'fuchsia-sdk', 'nacl', 'pdfium', 'skia', 'src-internal', 'webrtc')
660 ) | set('%[email protected]' % s for s in ('findit-for-me',))
Eric Boren6fd2b932018-01-25 15:05:08661
662
[email protected]55459852011-08-10 15:17:19663def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
664 """Attempts to prevent use of functions intended only for testing in
665 non-testing code. For now this is just a best-effort implementation
666 that ignores header files and may have some false positives. A
667 better implementation would probably need a proper C++ parser.
668 """
669 # We only scan .cc files and the like, as the declaration of
670 # for-testing functions in header files are hard to distinguish from
671 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44672 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19673
jochenc0d4808c2015-07-27 09:25:42674 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19675 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09676 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19677 exclusion_pattern = input_api.re.compile(
678 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
679 base_function_pattern, base_function_pattern))
680
681 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44682 black_list = (_EXCLUDED_PATHS +
683 _TEST_CODE_EXCLUDED_PATHS +
684 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19685 return input_api.FilterSourceFile(
686 affected_file,
687 white_list=(file_inclusion_pattern, ),
688 black_list=black_list)
689
690 problems = []
691 for f in input_api.AffectedSourceFiles(FilterFile):
692 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24693 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03694 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46695 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03696 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19697 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03698 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19699
700 if problems:
[email protected]f7051d52013-04-02 18:31:42701 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03702 else:
703 return []
[email protected]55459852011-08-10 15:17:19704
705
Vaclav Brozek7dbc28c2018-03-27 08:35:23706def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
707 """This is a simplified version of
708 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
709 """
710 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
711 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
712 name_pattern = r'ForTest(s|ing)?'
713 # Describes an occurrence of "ForTest*" inside a // comment.
714 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
715 # Catch calls.
716 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
717 # Ignore definitions. (Comments are ignored separately.)
718 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
719
720 problems = []
721 sources = lambda x: input_api.FilterSourceFile(
722 x,
723 black_list=(('(?i).*test', r'.*\/junit\/')
724 + input_api.DEFAULT_BLACK_LIST),
725 white_list=(r'.*\.java$',)
726 )
727 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
728 local_path = f.LocalPath()
729 is_inside_javadoc = False
730 for line_number, line in f.ChangedContents():
731 if is_inside_javadoc and javadoc_end_re.search(line):
732 is_inside_javadoc = False
733 if not is_inside_javadoc and javadoc_start_re.search(line):
734 is_inside_javadoc = True
735 if is_inside_javadoc:
736 continue
737 if (inclusion_re.search(line) and
738 not comment_re.search(line) and
739 not exclusion_re.search(line)):
740 problems.append(
741 '%s:%d\n %s' % (local_path, line_number, line.strip()))
742
743 if problems:
744 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
745 else:
746 return []
747
748
[email protected]10689ca2011-09-02 02:31:54749def _CheckNoIOStreamInHeaders(input_api, output_api):
750 """Checks to make sure no .h files include <iostream>."""
751 files = []
752 pattern = input_api.re.compile(r'^#include\s*<iostream>',
753 input_api.re.MULTILINE)
754 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
755 if not f.LocalPath().endswith('.h'):
756 continue
757 contents = input_api.ReadFile(f)
758 if pattern.search(contents):
759 files.append(f)
760
761 if len(files):
yolandyandaabc6d2016-04-18 18:29:39762 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06763 'Do not #include <iostream> in header files, since it inserts static '
764 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54765 '#include <ostream>. See http://crbug.com/94794',
766 files) ]
767 return []
768
769
[email protected]72df4e782012-06-21 16:28:18770def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52771 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18772 problems = []
773 for f in input_api.AffectedFiles():
774 if (not f.LocalPath().endswith(('.cc', '.mm'))):
775 continue
776
777 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04778 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18779 problems.append(' %s:%d' % (f.LocalPath(), line_num))
780
781 if not problems:
782 return []
783 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
784 '\n'.join(problems))]
785
786
danakj61c1aa22015-10-26 19:55:52787def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57788 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52789 errors = []
790 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
791 input_api.re.MULTILINE)
792 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
793 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
794 continue
795 for lnum, line in f.ChangedContents():
796 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17797 errors.append(output_api.PresubmitError(
798 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57799 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17800 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52801 return errors
802
803
mcasasb7440c282015-02-04 14:52:19804def _FindHistogramNameInLine(histogram_name, line):
805 """Tries to find a histogram name or prefix in a line."""
806 if not "affected-histogram" in line:
807 return histogram_name in line
808 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
809 # the histogram_name.
810 if not '"' in line:
811 return False
812 histogram_prefix = line.split('\"')[1]
813 return histogram_prefix in histogram_name
814
815
816def _CheckUmaHistogramChanges(input_api, output_api):
817 """Check that UMA histogram names in touched lines can still be found in other
818 lines of the patch or in histograms.xml. Note that this check would not catch
819 the reverse: changes in histograms.xml not matched in the code itself."""
820 touched_histograms = []
821 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:47822 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
823 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
824 name_pattern = r'"(.*?)"'
825 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
826 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
827 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
828 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
829 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:17830 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:19831 for f in input_api.AffectedFiles():
832 # If histograms.xml itself is modified, keep the modified lines for later.
833 if f.LocalPath().endswith(('histograms.xml')):
834 histograms_xml_modifications = f.ChangedContents()
835 continue
Vaclav Brozekbdac817c2018-03-24 06:30:47836 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
837 single_line_re = single_line_c_re
838 split_line_prefix_re = split_line_c_prefix_re
839 elif f.LocalPath().endswith(('java')):
840 single_line_re = single_line_java_re
841 split_line_prefix_re = split_line_java_prefix_re
842 else:
mcasasb7440c282015-02-04 14:52:19843 continue
844 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:17845 if last_line_matched_prefix:
846 suffix_found = split_line_suffix_re.search(line)
847 if suffix_found :
848 touched_histograms.append([suffix_found.group(1), f, line_num])
849 last_line_matched_prefix = False
850 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:06851 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:19852 if found:
853 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:17854 continue
855 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:19856
857 # Search for the touched histogram names in the local modifications to
858 # histograms.xml, and, if not found, on the base histograms.xml file.
859 unmatched_histograms = []
860 for histogram_info in touched_histograms:
861 histogram_name_found = False
862 for line_num, line in histograms_xml_modifications:
863 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
864 if histogram_name_found:
865 break
866 if not histogram_name_found:
867 unmatched_histograms.append(histogram_info)
868
eromanb90c82e7e32015-04-01 15:13:49869 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19870 problems = []
871 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49872 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19873 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45874 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19875 histogram_name_found = False
876 for line in histograms_xml:
877 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
878 if histogram_name_found:
879 break
880 if not histogram_name_found:
881 problems.append(' [%s:%d] %s' %
882 (f.LocalPath(), line_num, histogram_name))
883
884 if not problems:
885 return []
886 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
887 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49888 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19889
wnwenbdc444e2016-05-25 13:44:15890
yolandyandaabc6d2016-04-18 18:29:39891def _CheckFlakyTestUsage(input_api, output_api):
892 """Check that FlakyTest annotation is our own instead of the android one"""
893 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
894 files = []
895 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
896 if f.LocalPath().endswith('Test.java'):
897 if pattern.search(input_api.ReadFile(f)):
898 files.append(f)
899 if len(files):
900 return [output_api.PresubmitError(
901 'Use org.chromium.base.test.util.FlakyTest instead of '
902 'android.test.FlakyTest',
903 files)]
904 return []
mcasasb7440c282015-02-04 14:52:19905
wnwenbdc444e2016-05-25 13:44:15906
[email protected]8ea5d4b2011-09-13 21:49:22907def _CheckNoNewWStrings(input_api, output_api):
908 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27909 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22910 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20911 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57912 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34913 '/win/' in f.LocalPath() or
914 'chrome_elf' in f.LocalPath() or
915 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20916 continue
[email protected]8ea5d4b2011-09-13 21:49:22917
[email protected]a11dbe9b2012-08-07 01:32:58918 allowWString = False
[email protected]b5c24292011-11-28 14:38:20919 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58920 if 'presubmit: allow wstring' in line:
921 allowWString = True
922 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27923 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58924 allowWString = False
925 else:
926 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22927
[email protected]55463aa62011-10-12 00:48:27928 if not problems:
929 return []
930 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58931 ' If you are calling a cross-platform API that accepts a wstring, '
932 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27933 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22934
935
[email protected]2a8ac9c2011-10-19 17:20:44936def _CheckNoDEPSGIT(input_api, output_api):
937 """Make sure .DEPS.git is never modified manually."""
938 if any(f.LocalPath().endswith('.DEPS.git') for f in
939 input_api.AffectedFiles()):
940 return [output_api.PresubmitError(
941 'Never commit changes to .DEPS.git. This file is maintained by an\n'
942 'automated system based on what\'s in DEPS and your changes will be\n'
943 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50944 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
945 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:44946 'for more information')]
947 return []
948
949
tandriief664692014-09-23 14:51:47950def _CheckValidHostsInDEPS(input_api, output_api):
951 """Checks that DEPS file deps are from allowed_hosts."""
952 # Run only if DEPS file has been modified to annoy fewer bystanders.
953 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
954 return []
955 # Outsource work to gclient verify
956 try:
957 input_api.subprocess.check_output(['gclient', 'verify'])
958 return []
959 except input_api.subprocess.CalledProcessError, error:
960 return [output_api.PresubmitError(
961 'DEPS file must have only git dependencies.',
962 long_text=error.output)]
963
964
[email protected]127f18ec2012-06-16 05:05:59965def _CheckNoBannedFunctions(input_api, output_api):
966 """Make sure that banned functions are not used."""
967 warnings = []
968 errors = []
969
wnwenbdc444e2016-05-25 13:44:15970 def IsBlacklisted(affected_file, blacklist):
971 local_path = affected_file.LocalPath()
972 for item in blacklist:
973 if input_api.re.match(item, local_path):
974 return True
975 return False
976
Sylvain Defresnea8b73d252018-02-28 15:45:54977 def IsIosObcjFile(affected_file):
978 local_path = affected_file.LocalPath()
979 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
980 return False
981 basename = input_api.os_path.basename(local_path)
982 if 'ios' in basename.split('_'):
983 return True
984 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
985 if sep and 'ios' in local_path.split(sep):
986 return True
987 return False
988
wnwenbdc444e2016-05-25 13:44:15989 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
990 matched = False
991 if func_name[0:1] == '/':
992 regex = func_name[1:]
993 if input_api.re.search(regex, line):
994 matched = True
995 elif func_name in line:
dchenge07de812016-06-20 19:27:17996 matched = True
wnwenbdc444e2016-05-25 13:44:15997 if matched:
dchenge07de812016-06-20 19:27:17998 problems = warnings
wnwenbdc444e2016-05-25 13:44:15999 if error:
dchenge07de812016-06-20 19:27:171000 problems = errors
wnwenbdc444e2016-05-25 13:44:151001 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
1002 for message_line in message:
1003 problems.append(' %s' % message_line)
1004
Eric Stevensona9a980972017-09-23 00:04:411005 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1006 for f in input_api.AffectedFiles(file_filter=file_filter):
1007 for line_num, line in f.ChangedContents():
1008 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1009 CheckForMatch(f, line_num, line, func_name, message, error)
1010
[email protected]127f18ec2012-06-16 05:05:591011 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1012 for f in input_api.AffectedFiles(file_filter=file_filter):
1013 for line_num, line in f.ChangedContents():
1014 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151015 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591016
Sylvain Defresnea8b73d252018-02-28 15:45:541017 for f in input_api.AffectedFiles(file_filter=IsIosObcjFile):
1018 for line_num, line in f.ChangedContents():
1019 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1020 CheckForMatch(f, line_num, line, func_name, message, error)
1021
[email protected]127f18ec2012-06-16 05:05:591022 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1023 for f in input_api.AffectedFiles(file_filter=file_filter):
1024 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491025 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491026 if IsBlacklisted(f, excluded_paths):
1027 continue
wnwenbdc444e2016-05-25 13:44:151028 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591029
1030 result = []
1031 if (warnings):
1032 result.append(output_api.PresubmitPromptWarning(
1033 'Banned functions were used.\n' + '\n'.join(warnings)))
1034 if (errors):
1035 result.append(output_api.PresubmitError(
1036 'Banned functions were used.\n' + '\n'.join(errors)))
1037 return result
1038
1039
[email protected]6c063c62012-07-11 19:11:061040def _CheckNoPragmaOnce(input_api, output_api):
1041 """Make sure that banned functions are not used."""
1042 files = []
1043 pattern = input_api.re.compile(r'^#pragma\s+once',
1044 input_api.re.MULTILINE)
1045 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1046 if not f.LocalPath().endswith('.h'):
1047 continue
1048 contents = input_api.ReadFile(f)
1049 if pattern.search(contents):
1050 files.append(f)
1051
1052 if files:
1053 return [output_api.PresubmitError(
1054 'Do not use #pragma once in header files.\n'
1055 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1056 files)]
1057 return []
1058
[email protected]127f18ec2012-06-16 05:05:591059
[email protected]e7479052012-09-19 00:26:121060def _CheckNoTrinaryTrueFalse(input_api, output_api):
1061 """Checks to make sure we don't introduce use of foo ? true : false."""
1062 problems = []
1063 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1064 for f in input_api.AffectedFiles():
1065 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1066 continue
1067
1068 for line_num, line in f.ChangedContents():
1069 if pattern.match(line):
1070 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1071
1072 if not problems:
1073 return []
1074 return [output_api.PresubmitPromptWarning(
1075 'Please consider avoiding the "? true : false" pattern if possible.\n' +
1076 '\n'.join(problems))]
1077
1078
[email protected]55f9f382012-07-31 11:02:181079def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:281080 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:181081 change. Breaking - rules is an error, breaking ! rules is a
1082 warning.
1083 """
mohan.reddyf21db962014-10-16 12:26:471084 import sys
[email protected]55f9f382012-07-31 11:02:181085 # We need to wait until we have an input_api object and use this
1086 # roundabout construct to import checkdeps because this file is
1087 # eval-ed and thus doesn't have __file__.
1088 original_sys_path = sys.path
1089 try:
1090 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:471091 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:181092 import checkdeps
1093 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:241094 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:281095 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:181096 from rules import Rule
1097 finally:
1098 # Restore sys.path to what it was before.
1099 sys.path = original_sys_path
1100
1101 added_includes = []
rhalavati08acd232017-04-03 07:23:281102 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:241103 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:181104 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:281105 if CppChecker.IsCppFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501106 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081107 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:281108 elif ProtoChecker.IsProtoFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501109 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081110 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:241111 elif JavaChecker.IsJavaFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501112 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081113 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:181114
[email protected]26385172013-05-09 23:11:351115 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181116
1117 error_descriptions = []
1118 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:281119 error_subjects = set()
1120 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:181121 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
1122 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:081123 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181124 description_with_path = '%s\n %s' % (path, rule_description)
1125 if rule_type == Rule.DISALLOW:
1126 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281127 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:181128 else:
1129 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281130 warning_subjects.add("#includes")
1131
1132 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
1133 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:081134 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:281135 description_with_path = '%s\n %s' % (path, rule_description)
1136 if rule_type == Rule.DISALLOW:
1137 error_descriptions.append(description_with_path)
1138 error_subjects.add("imports")
1139 else:
1140 warning_descriptions.append(description_with_path)
1141 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:181142
Jinsuk Kim5a092672017-10-24 22:42:241143 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:021144 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:081145 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:241146 description_with_path = '%s\n %s' % (path, rule_description)
1147 if rule_type == Rule.DISALLOW:
1148 error_descriptions.append(description_with_path)
1149 error_subjects.add("imports")
1150 else:
1151 warning_descriptions.append(description_with_path)
1152 warning_subjects.add("imports")
1153
[email protected]55f9f382012-07-31 11:02:181154 results = []
1155 if error_descriptions:
1156 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:281157 'You added one or more %s that violate checkdeps rules.'
1158 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:181159 error_descriptions))
1160 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:421161 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:281162 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:181163 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:281164 '%s? See relevant DEPS file(s) for details and contacts.' %
1165 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:181166 warning_descriptions))
1167 return results
1168
1169
[email protected]fbcafe5a2012-08-08 15:31:221170def _CheckFilePermissions(input_api, output_api):
1171 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:151172 if input_api.platform == 'win32':
1173 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:291174 checkperms_tool = input_api.os_path.join(
1175 input_api.PresubmitLocalPath(),
1176 'tools', 'checkperms', 'checkperms.py')
1177 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:471178 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:391179 with input_api.CreateTemporaryFile() as file_list:
1180 for f in input_api.AffectedFiles():
1181 # checkperms.py file/directory arguments must be relative to the
1182 # repository.
1183 file_list.write(f.LocalPath() + '\n')
1184 file_list.close()
1185 args += ['--file-list', file_list.name]
1186 try:
1187 input_api.subprocess.check_output(args)
1188 return []
1189 except input_api.subprocess.CalledProcessError as error:
1190 return [output_api.PresubmitError(
1191 'checkperms.py failed:',
1192 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:221193
1194
robertocn832f5992017-01-04 19:01:301195def _CheckTeamTags(input_api, output_api):
1196 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
1197 checkteamtags_tool = input_api.os_path.join(
1198 input_api.PresubmitLocalPath(),
1199 'tools', 'checkteamtags', 'checkteamtags.py')
1200 args = [input_api.python_executable, checkteamtags_tool,
1201 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:221202 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:301203 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
1204 'OWNERS']
1205 try:
1206 if files:
1207 input_api.subprocess.check_output(args + files)
1208 return []
1209 except input_api.subprocess.CalledProcessError as error:
1210 return [output_api.PresubmitError(
1211 'checkteamtags.py failed:',
1212 long_text=error.output)]
1213
1214
[email protected]c8278b32012-10-30 20:35:491215def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
1216 """Makes sure we don't include ui/aura/window_property.h
1217 in header files.
1218 """
1219 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1220 errors = []
1221 for f in input_api.AffectedFiles():
1222 if not f.LocalPath().endswith('.h'):
1223 continue
1224 for line_num, line in f.ChangedContents():
1225 if pattern.match(line):
1226 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1227
1228 results = []
1229 if errors:
1230 results.append(output_api.PresubmitError(
1231 'Header files should not include ui/aura/window_property.h', errors))
1232 return results
1233
1234
[email protected]70ca77752012-11-20 03:45:031235def _CheckForVersionControlConflictsInFile(input_api, f):
1236 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1237 errors = []
1238 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231239 if f.LocalPath().endswith('.md'):
1240 # First-level headers in markdown look a lot like version control
1241 # conflict markers. http://daringfireball.net/projects/markdown/basics
1242 continue
[email protected]70ca77752012-11-20 03:45:031243 if pattern.match(line):
1244 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1245 return errors
1246
1247
1248def _CheckForVersionControlConflicts(input_api, output_api):
1249 """Usually this is not intentional and will cause a compile failure."""
1250 errors = []
1251 for f in input_api.AffectedFiles():
1252 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1253
1254 results = []
1255 if errors:
1256 results.append(output_api.PresubmitError(
1257 'Version control conflict markers found, please resolve.', errors))
1258 return results
1259
estadee17314a02017-01-12 16:22:161260def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1261 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1262 errors = []
1263 for f in input_api.AffectedFiles():
1264 for line_num, line in f.ChangedContents():
1265 if pattern.search(line):
1266 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1267
1268 results = []
1269 if errors:
1270 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:501271 'Found Google support URL addressed by answer number. Please replace '
1272 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:161273 return results
1274
[email protected]70ca77752012-11-20 03:45:031275
[email protected]06e6d0ff2012-12-11 01:36:441276def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1277 def FilterFile(affected_file):
1278 """Filter function for use with input_api.AffectedSourceFiles,
1279 below. This filters out everything except non-test files from
1280 top-level directories that generally speaking should not hard-code
1281 service URLs (e.g. src/android_webview/, src/content/ and others).
1282 """
1283 return input_api.FilterSourceFile(
1284 affected_file,
[email protected]78bb39d62012-12-11 15:11:561285 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441286 black_list=(_EXCLUDED_PATHS +
1287 _TEST_CODE_EXCLUDED_PATHS +
1288 input_api.DEFAULT_BLACK_LIST))
1289
reillyi38965732015-11-16 18:27:331290 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1291 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461292 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1293 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441294 problems = [] # items are (filename, line_number, line)
1295 for f in input_api.AffectedSourceFiles(FilterFile):
1296 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461297 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441298 problems.append((f.LocalPath(), line_num, line))
1299
1300 if problems:
[email protected]f7051d52013-04-02 18:31:421301 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441302 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581303 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441304 [' %s:%d: %s' % (
1305 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031306 else:
1307 return []
[email protected]06e6d0ff2012-12-11 01:36:441308
1309
[email protected]d2530012013-01-25 16:39:271310def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1311 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311312 The native_client_sdk directory is excluded because it has auto-generated PNG
1313 files for documentation.
[email protected]d2530012013-01-25 16:39:271314 """
[email protected]d2530012013-01-25 16:39:271315 errors = []
binji0dcdf342014-12-12 18:32:311316 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1317 black_list = (r'^native_client_sdk[\\\/]',)
1318 file_filter = lambda f: input_api.FilterSourceFile(
1319 f, white_list=white_list, black_list=black_list)
1320 for f in input_api.AffectedFiles(include_deletes=False,
1321 file_filter=file_filter):
1322 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271323
1324 results = []
1325 if errors:
1326 results.append(output_api.PresubmitError(
1327 'The name of PNG files should not have abbreviations. \n'
1328 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1329 'Contact [email protected] if you have questions.', errors))
1330 return results
1331
1332
Daniel Cheng4dcdb6b2017-04-13 08:30:171333def _ExtractAddRulesFromParsedDeps(parsed_deps):
1334 """Extract the rules that add dependencies from a parsed DEPS file.
1335
1336 Args:
1337 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1338 add_rules = set()
1339 add_rules.update([
1340 rule[1:] for rule in parsed_deps.get('include_rules', [])
1341 if rule.startswith('+') or rule.startswith('!')
1342 ])
Vaclav Brozekd5de76a2018-03-17 07:57:501343 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:171344 {}).iteritems():
1345 add_rules.update([
1346 rule[1:] for rule in rules
1347 if rule.startswith('+') or rule.startswith('!')
1348 ])
1349 return add_rules
1350
1351
1352def _ParseDeps(contents):
1353 """Simple helper for parsing DEPS files."""
1354 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171355 class _VarImpl:
1356
1357 def __init__(self, local_scope):
1358 self._local_scope = local_scope
1359
1360 def Lookup(self, var_name):
1361 """Implements the Var syntax."""
1362 try:
1363 return self._local_scope['vars'][var_name]
1364 except KeyError:
1365 raise Exception('Var is not defined: %s' % var_name)
1366
1367 local_scope = {}
1368 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171369 'Var': _VarImpl(local_scope).Lookup,
1370 }
1371 exec contents in global_scope, local_scope
1372 return local_scope
1373
1374
1375def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081376 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411377 a set of DEPS entries that we should look up.
1378
1379 For a directory (rather than a specific filename) we fake a path to
1380 a specific filename by adding /DEPS. This is chosen as a file that
1381 will seldom or never be subject to per-file include_rules.
1382 """
[email protected]2b438d62013-11-14 17:54:141383 # We ignore deps entries on auto-generated directories.
1384 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081385
Daniel Cheng4dcdb6b2017-04-13 08:30:171386 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1387 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1388
1389 added_deps = new_deps.difference(old_deps)
1390
[email protected]2b438d62013-11-14 17:54:141391 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171392 for added_dep in added_deps:
1393 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1394 continue
1395 # Assume that a rule that ends in .h is a rule for a specific file.
1396 if added_dep.endswith('.h'):
1397 results.add(added_dep)
1398 else:
1399 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081400 return results
1401
1402
[email protected]e871964c2013-05-13 14:14:551403def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1404 """When a dependency prefixed with + is added to a DEPS file, we
1405 want to make sure that the change is reviewed by an OWNER of the
1406 target file or directory, to avoid layering violations from being
1407 introduced. This check verifies that this happens.
1408 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171409 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241410
1411 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191412 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241413 for f in input_api.AffectedFiles(include_deletes=False,
1414 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551415 filename = input_api.os_path.basename(f.LocalPath())
1416 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171417 virtual_depended_on_files.update(_CalculateAddedDeps(
1418 input_api.os_path,
1419 '\n'.join(f.OldContents()),
1420 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551421
[email protected]e871964c2013-05-13 14:14:551422 if not virtual_depended_on_files:
1423 return []
1424
1425 if input_api.is_committing:
1426 if input_api.tbr:
1427 return [output_api.PresubmitNotifyResult(
1428 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271429 if input_api.dry_run:
1430 return [output_api.PresubmitNotifyResult(
1431 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551432 if not input_api.change.issue:
1433 return [output_api.PresubmitError(
1434 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401435 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551436 output = output_api.PresubmitError
1437 else:
1438 output = output_api.PresubmitNotifyResult
1439
1440 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501441 owner_email, reviewers = (
1442 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1443 input_api,
1444 owners_db.email_regexp,
1445 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551446
1447 owner_email = owner_email or input_api.change.author_email
1448
[email protected]de4f7d22013-05-23 14:27:461449 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511450 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461451 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551452 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1453 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411454
1455 # We strip the /DEPS part that was added by
1456 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1457 # directory.
1458 def StripDeps(path):
1459 start_deps = path.rfind('/DEPS')
1460 if start_deps != -1:
1461 return path[:start_deps]
1462 else:
1463 return path
1464 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551465 for path in missing_files]
1466
1467 if unapproved_dependencies:
1468 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151469 output('You need LGTM from owners of depends-on paths in DEPS that were '
1470 'modified in this CL:\n %s' %
1471 '\n '.join(sorted(unapproved_dependencies)))]
1472 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1473 output_list.append(output(
1474 'Suggested missing target path OWNERS:\n %s' %
1475 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551476 return output_list
1477
1478 return []
1479
1480
[email protected]85218562013-11-22 07:41:401481def _CheckSpamLogging(input_api, output_api):
1482 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1483 black_list = (_EXCLUDED_PATHS +
1484 _TEST_CODE_EXCLUDED_PATHS +
1485 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501486 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191487 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481488 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461489 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121490 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1491 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581492 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161493 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031494 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151495 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1496 r"^chromecast[\\\/]",
1497 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481498 r"^components[\\\/]browser_watcher[\\\/]"
1499 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311500 r"^components[\\\/]html_viewer[\\\/]"
1501 r"web_test_delegate_impl\.cc$",
Samuel Huang577ef6c2018-03-13 18:19:341502 r"^components[\\\/]zucchini[\\\/].*",
peter80739bb2015-10-20 11:17:461503 # TODO(peter): Remove this exception. https://crbug.com/534537
1504 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1505 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251506 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1507 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241508 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111509 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151510 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111511 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521512 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501513 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361514 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311515 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131516 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001517 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441518 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451519 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021520 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351521 r"dump_file_system.cc$",
1522 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401523 source_file_filter = lambda x: input_api.FilterSourceFile(
1524 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1525
thomasanderson625d3932017-03-29 07:16:581526 log_info = set([])
1527 printf = set([])
[email protected]85218562013-11-22 07:41:401528
1529 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581530 for _, line in f.ChangedContents():
1531 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1532 log_info.add(f.LocalPath())
1533 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1534 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371535
thomasanderson625d3932017-03-29 07:16:581536 if input_api.re.search(r"\bprintf\(", line):
1537 printf.add(f.LocalPath())
1538 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1539 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401540
1541 if log_info:
1542 return [output_api.PresubmitError(
1543 'These files spam the console log with LOG(INFO):',
1544 items=log_info)]
1545 if printf:
1546 return [output_api.PresubmitError(
1547 'These files spam the console log with printf/fprintf:',
1548 items=printf)]
1549 return []
1550
1551
[email protected]49aa76a2013-12-04 06:59:161552def _CheckForAnonymousVariables(input_api, output_api):
1553 """These types are all expected to hold locks while in scope and
1554 so should never be anonymous (which causes them to be immediately
1555 destroyed)."""
1556 they_who_must_be_named = [
1557 'base::AutoLock',
1558 'base::AutoReset',
1559 'base::AutoUnlock',
1560 'SkAutoAlphaRestore',
1561 'SkAutoBitmapShaderInstall',
1562 'SkAutoBlitterChoose',
1563 'SkAutoBounderCommit',
1564 'SkAutoCallProc',
1565 'SkAutoCanvasRestore',
1566 'SkAutoCommentBlock',
1567 'SkAutoDescriptor',
1568 'SkAutoDisableDirectionCheck',
1569 'SkAutoDisableOvalCheck',
1570 'SkAutoFree',
1571 'SkAutoGlyphCache',
1572 'SkAutoHDC',
1573 'SkAutoLockColors',
1574 'SkAutoLockPixels',
1575 'SkAutoMalloc',
1576 'SkAutoMaskFreeImage',
1577 'SkAutoMutexAcquire',
1578 'SkAutoPathBoundsUpdate',
1579 'SkAutoPDFRelease',
1580 'SkAutoRasterClipValidate',
1581 'SkAutoRef',
1582 'SkAutoTime',
1583 'SkAutoTrace',
1584 'SkAutoUnref',
1585 ]
1586 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1587 # bad: base::AutoLock(lock.get());
1588 # not bad: base::AutoLock lock(lock.get());
1589 bad_pattern = input_api.re.compile(anonymous)
1590 # good: new base::AutoLock(lock.get())
1591 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1592 errors = []
1593
1594 for f in input_api.AffectedFiles():
1595 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1596 continue
1597 for linenum, line in f.ChangedContents():
1598 if bad_pattern.search(line) and not good_pattern.search(line):
1599 errors.append('%s:%d' % (f.LocalPath(), linenum))
1600
1601 if errors:
1602 return [output_api.PresubmitError(
1603 'These lines create anonymous variables that need to be named:',
1604 items=errors)]
1605 return []
1606
1607
Peter Kasting4844e46e2018-02-23 07:27:101608def _CheckUniquePtr(input_api, output_api):
1609 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1610 sources = lambda affected_file: input_api.FilterSourceFile(
1611 affected_file,
1612 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1613 input_api.DEFAULT_BLACK_LIST),
1614 white_list=(file_inclusion_pattern,))
Vaclav Brozeka54c528b2018-04-06 19:23:551615
1616 # Pattern to capture a single "<...>" block of template arguments. It can
1617 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
1618 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
1619 # latter would likely require counting that < and > match, which is not
1620 # expressible in regular languages. Should the need arise, one can introduce
1621 # limited counting (matching up to a total number of nesting depth), which
1622 # should cover all practical cases for already a low nesting limit.
1623 template_arg_pattern = (
1624 r'<[^>]*' # Opening block of <.
1625 r'>([^<]*>)?') # Closing block of >.
1626 # Prefix expressing that whatever follows is not already inside a <...>
1627 # block.
1628 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:101629 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:551630 not_inside_template_arg_pattern
1631 + r'\bstd::unique_ptr'
1632 + template_arg_pattern
1633 + r'\(\)')
1634
1635 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
1636 template_arg_no_array_pattern = (
1637 r'<[^>]*[^]]' # Opening block of <.
1638 r'>([^(<]*[^]]>)?') # Closing block of >.
1639 # Prefix saying that what follows is the start of an expression.
1640 start_of_expr_pattern = r'(=|\breturn|^)\s*'
1641 # Suffix saying that what follows are call parentheses with a non-empty list
1642 # of arguments.
1643 nonempty_arg_list_pattern = r'\(([^)]|$)'
1644 return_construct_pattern = input_api.re.compile(
1645 start_of_expr_pattern
1646 + r'std::unique_ptr'
1647 + template_arg_no_array_pattern
1648 + nonempty_arg_list_pattern)
1649
Vaclav Brozek851d9602018-04-04 16:13:051650 problems_constructor = []
1651 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:101652 for f in input_api.AffectedSourceFiles(sources):
1653 for line_number, line in f.ChangedContents():
1654 # Disallow:
1655 # return std::unique_ptr<T>(foo);
1656 # bar = std::unique_ptr<T>(foo);
1657 # But allow:
1658 # return std::unique_ptr<T[]>(foo);
1659 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozek851d9602018-04-04 16:13:051660 local_path = f.LocalPath()
Peter Kasting4844e46e2018-02-23 07:27:101661 if return_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:051662 problems_constructor.append(
1663 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:101664 # Disallow:
1665 # std::unique_ptr<T>()
1666 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:051667 problems_nullptr.append(
1668 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1669
1670 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:161671 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:051672 errors.append(output_api.PresubmitError(
1673 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:161674 problems_nullptr))
1675 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:051676 errors.append(output_api.PresubmitError(
1677 'The following files use explicit std::unique_ptr constructor.'
1678 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:161679 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:101680 return errors
1681
1682
[email protected]999261d2014-03-03 20:08:081683def _CheckUserActionUpdate(input_api, output_api):
1684 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521685 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081686 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521687 # If actions.xml is already included in the changelist, the PRESUBMIT
1688 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081689 return []
1690
[email protected]999261d2014-03-03 20:08:081691 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1692 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521693 current_actions = None
[email protected]999261d2014-03-03 20:08:081694 for f in input_api.AffectedFiles(file_filter=file_filter):
1695 for line_num, line in f.ChangedContents():
1696 match = input_api.re.search(action_re, line)
1697 if match:
[email protected]2f92dec2014-03-07 19:21:521698 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1699 # loaded only once.
1700 if not current_actions:
1701 with open('tools/metrics/actions/actions.xml') as actions_f:
1702 current_actions = actions_f.read()
1703 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081704 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521705 action = 'name="{0}"'.format(action_name)
1706 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081707 return [output_api.PresubmitPromptWarning(
1708 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521709 'tools/metrics/actions/actions.xml. Please run '
1710 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081711 % (f.LocalPath(), line_num, action_name))]
1712 return []
1713
1714
Daniel Cheng13ca61a882017-08-25 15:11:251715def _ImportJSONCommentEater(input_api):
1716 import sys
1717 sys.path = sys.path + [input_api.os_path.join(
1718 input_api.PresubmitLocalPath(),
1719 'tools', 'json_comment_eater')]
1720 import json_comment_eater
1721 return json_comment_eater
1722
1723
[email protected]99171a92014-06-03 08:44:471724def _GetJSONParseError(input_api, filename, eat_comments=True):
1725 try:
1726 contents = input_api.ReadFile(filename)
1727 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251728 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131729 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471730
1731 input_api.json.loads(contents)
1732 except ValueError as e:
1733 return e
1734 return None
1735
1736
1737def _GetIDLParseError(input_api, filename):
1738 try:
1739 contents = input_api.ReadFile(filename)
1740 idl_schema = input_api.os_path.join(
1741 input_api.PresubmitLocalPath(),
1742 'tools', 'json_schema_compiler', 'idl_schema.py')
1743 process = input_api.subprocess.Popen(
1744 [input_api.python_executable, idl_schema],
1745 stdin=input_api.subprocess.PIPE,
1746 stdout=input_api.subprocess.PIPE,
1747 stderr=input_api.subprocess.PIPE,
1748 universal_newlines=True)
1749 (_, error) = process.communicate(input=contents)
1750 return error or None
1751 except ValueError as e:
1752 return e
1753
1754
1755def _CheckParseErrors(input_api, output_api):
1756 """Check that IDL and JSON files do not contain syntax errors."""
1757 actions = {
1758 '.idl': _GetIDLParseError,
1759 '.json': _GetJSONParseError,
1760 }
[email protected]99171a92014-06-03 08:44:471761 # Most JSON files are preprocessed and support comments, but these do not.
1762 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491763 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471764 ]
1765 # Only run IDL checker on files in these directories.
1766 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491767 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1768 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471769 ]
1770
1771 def get_action(affected_file):
1772 filename = affected_file.LocalPath()
1773 return actions.get(input_api.os_path.splitext(filename)[1])
1774
[email protected]99171a92014-06-03 08:44:471775 def FilterFile(affected_file):
1776 action = get_action(affected_file)
1777 if not action:
1778 return False
1779 path = affected_file.LocalPath()
1780
Sean Kau46e29bc2017-08-28 16:31:161781 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471782 return False
1783
1784 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161785 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471786 return False
1787 return True
1788
1789 results = []
1790 for affected_file in input_api.AffectedFiles(
1791 file_filter=FilterFile, include_deletes=False):
1792 action = get_action(affected_file)
1793 kwargs = {}
1794 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161795 _MatchesFile(input_api, json_no_comments_patterns,
1796 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471797 kwargs['eat_comments'] = False
1798 parse_error = action(input_api,
1799 affected_file.AbsoluteLocalPath(),
1800 **kwargs)
1801 if parse_error:
1802 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1803 (affected_file.LocalPath(), parse_error)))
1804 return results
1805
1806
[email protected]760deea2013-12-10 19:33:491807def _CheckJavaStyle(input_api, output_api):
1808 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471809 import sys
[email protected]760deea2013-12-10 19:33:491810 original_sys_path = sys.path
1811 try:
1812 sys.path = sys.path + [input_api.os_path.join(
1813 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1814 import checkstyle
1815 finally:
1816 # Restore sys.path to what it was before.
1817 sys.path = original_sys_path
1818
1819 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091820 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511821 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491822
1823
Sean Kau46e29bc2017-08-28 16:31:161824def _MatchesFile(input_api, patterns, path):
1825 for pattern in patterns:
1826 if input_api.re.search(pattern, path):
1827 return True
1828 return False
1829
1830
Daniel Cheng7052cdf2017-11-21 19:23:291831def _GetOwnersFilesToCheckForIpcOwners(input_api):
1832 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:171833
Daniel Cheng7052cdf2017-11-21 19:23:291834 Returns:
1835 A dictionary mapping an OWNER file to the list of OWNERS rules it must
1836 contain to cover IPC-related files with noparent reviewer rules.
1837 """
1838 # Whether or not a file affects IPC is (mostly) determined by a simple list
1839 # of filename patterns.
dchenge07de812016-06-20 19:27:171840 file_patterns = [
palmerb19a0932017-01-24 04:00:311841 # Legacy IPC:
dchenge07de812016-06-20 19:27:171842 '*_messages.cc',
1843 '*_messages*.h',
1844 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311845 # Mojo IPC:
dchenge07de812016-06-20 19:27:171846 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:471847 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:171848 '*_struct_traits*.*',
1849 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311850 '*.typemap',
1851 # Android native IPC:
1852 '*.aidl',
1853 # Blink uses a different file naming convention:
1854 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:471855 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:171856 '*StructTraits*.*',
1857 '*TypeConverter*.*',
1858 ]
1859
scottmg7a6ed5ba2016-11-04 18:22:041860 # These third_party directories do not contain IPCs, but contain files
1861 # matching the above patterns, which trigger false positives.
1862 exclude_paths = [
1863 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291864 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041865 ]
1866
dchenge07de812016-06-20 19:27:171867 # Dictionary mapping an OWNERS file path to Patterns.
1868 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1869 # rules ) to a PatternEntry.
1870 # PatternEntry is a dictionary with two keys:
1871 # - 'files': the files that are matched by this pattern
1872 # - 'rules': the per-file rules needed for this pattern
1873 # For example, if we expect OWNERS file to contain rules for *.mojom and
1874 # *_struct_traits*.*, Patterns might look like this:
1875 # {
1876 # '*.mojom': {
1877 # 'files': ...,
1878 # 'rules': [
1879 # 'per-file *.mojom=set noparent',
1880 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1881 # ],
1882 # },
1883 # '*_struct_traits*.*': {
1884 # 'files': ...,
1885 # 'rules': [
1886 # 'per-file *_struct_traits*.*=set noparent',
1887 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1888 # ],
1889 # },
1890 # }
1891 to_check = {}
1892
Daniel Cheng13ca61a882017-08-25 15:11:251893 def AddPatternToCheck(input_file, pattern):
1894 owners_file = input_api.os_path.join(
1895 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1896 if owners_file not in to_check:
1897 to_check[owners_file] = {}
1898 if pattern not in to_check[owners_file]:
1899 to_check[owners_file][pattern] = {
1900 'files': [],
1901 'rules': [
1902 'per-file %s=set noparent' % pattern,
1903 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1904 ]
1905 }
Vaclav Brozekd5de76a2018-03-17 07:57:501906 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:251907
dchenge07de812016-06-20 19:27:171908 # Iterate through the affected files to see what we actually need to check
1909 # for. We should only nag patch authors about per-file rules if a file in that
1910 # directory would match that pattern. If a directory only contains *.mojom
1911 # files and no *_messages*.h files, we should only nag about rules for
1912 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251913 for f in input_api.AffectedFiles(include_deletes=False):
1914 # Manifest files don't have a strong naming convention. Instead, scan
1915 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161916 if (f.LocalPath().endswith('.json') and
1917 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1918 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251919 json_comment_eater = _ImportJSONCommentEater(input_api)
1920 mostly_json_lines = '\n'.join(f.NewContents())
1921 # Comments aren't allowed in strict JSON, so filter them out.
1922 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:431923 try:
1924 json_content = input_api.json.loads(json_lines)
1925 except:
1926 # There's another PRESUBMIT check that already verifies that JSON files
1927 # are not invalid, so no need to emit another warning here.
1928 continue
Daniel Cheng13ca61a882017-08-25 15:11:251929 if 'interface_provider_specs' in json_content:
1930 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171931 for pattern in file_patterns:
1932 if input_api.fnmatch.fnmatch(
1933 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041934 skip = False
1935 for exclude in exclude_paths:
1936 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1937 skip = True
1938 break
1939 if skip:
1940 continue
Daniel Cheng13ca61a882017-08-25 15:11:251941 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171942 break
1943
Daniel Cheng7052cdf2017-11-21 19:23:291944 return to_check
1945
1946
1947def _CheckIpcOwners(input_api, output_api):
1948 """Checks that affected files involving IPC have an IPC OWNERS rule."""
1949 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
1950
1951 if to_check:
1952 # If there are any OWNERS files to check, there are IPC-related changes in
1953 # this CL. Auto-CC the review list.
1954 output_api.AppendCC('[email protected]')
1955
1956 # Go through the OWNERS files to check, filtering out rules that are already
1957 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:171958 for owners_file, patterns in to_check.iteritems():
1959 try:
1960 with file(owners_file) as f:
1961 lines = set(f.read().splitlines())
1962 for entry in patterns.itervalues():
1963 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1964 ]
1965 except IOError:
1966 # No OWNERS file, so all the rules are definitely missing.
1967 continue
1968
1969 # All the remaining lines weren't found in OWNERS files, so emit an error.
1970 errors = []
1971 for owners_file, patterns in to_check.iteritems():
1972 missing_lines = []
1973 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:501974 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:171975 missing_lines.extend(entry['rules'])
1976 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1977 if missing_lines:
1978 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:051979 'Because of the presence of files:\n%s\n\n'
1980 '%s needs the following %d lines added:\n\n%s' %
1981 ('\n'.join(files), owners_file, len(missing_lines),
1982 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:171983
1984 results = []
1985 if errors:
vabrf5ce3bf92016-07-11 14:52:411986 if input_api.is_committing:
1987 output = output_api.PresubmitError
1988 else:
1989 output = output_api.PresubmitPromptWarning
1990 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591991 'Found OWNERS files that need to be updated for IPC security ' +
1992 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171993 long_text='\n\n'.join(errors)))
1994
1995 return results
1996
1997
jbriance9e12f162016-11-25 07:57:501998def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311999 """Checks that added or removed lines in non third party affected
2000 header files do not lead to new useless class or struct forward
2001 declaration.
jbriance9e12f162016-11-25 07:57:502002 """
2003 results = []
2004 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
2005 input_api.re.MULTILINE)
2006 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
2007 input_api.re.MULTILINE)
2008 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:312009 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:192010 not f.LocalPath().startswith('third_party/blink') and
2011 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:312012 not f.LocalPath().startswith('third_party/WebKit') and
2013 not f.LocalPath().startswith('third_party\\WebKit')):
2014 continue
2015
jbriance9e12f162016-11-25 07:57:502016 if not f.LocalPath().endswith('.h'):
2017 continue
2018
2019 contents = input_api.ReadFile(f)
2020 fwd_decls = input_api.re.findall(class_pattern, contents)
2021 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
2022
2023 useless_fwd_decls = []
2024 for decl in fwd_decls:
2025 count = sum(1 for _ in input_api.re.finditer(
2026 r'\b%s\b' % input_api.re.escape(decl), contents))
2027 if count == 1:
2028 useless_fwd_decls.append(decl)
2029
2030 if not useless_fwd_decls:
2031 continue
2032
2033 for line in f.GenerateScmDiff().splitlines():
2034 if (line.startswith('-') and not line.startswith('--') or
2035 line.startswith('+') and not line.startswith('++')):
2036 for decl in useless_fwd_decls:
2037 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
2038 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:242039 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:502040 (f.LocalPath(), decl)))
2041 useless_fwd_decls.remove(decl)
2042
2043 return results
2044
2045
dskiba88634f4e2015-08-14 23:03:292046def _CheckAndroidToastUsage(input_api, output_api):
2047 """Checks that code uses org.chromium.ui.widget.Toast instead of
2048 android.widget.Toast (Chromium Toast doesn't force hardware
2049 acceleration on low-end devices, saving memory).
2050 """
2051 toast_import_pattern = input_api.re.compile(
2052 r'^import android\.widget\.Toast;$')
2053
2054 errors = []
2055
2056 sources = lambda affected_file: input_api.FilterSourceFile(
2057 affected_file,
2058 black_list=(_EXCLUDED_PATHS +
2059 _TEST_CODE_EXCLUDED_PATHS +
2060 input_api.DEFAULT_BLACK_LIST +
2061 (r'^chromecast[\\\/].*',
2062 r'^remoting[\\\/].*')),
2063 white_list=(r'.*\.java$',))
2064
2065 for f in input_api.AffectedSourceFiles(sources):
2066 for line_num, line in f.ChangedContents():
2067 if toast_import_pattern.search(line):
2068 errors.append("%s:%d" % (f.LocalPath(), line_num))
2069
2070 results = []
2071
2072 if errors:
2073 results.append(output_api.PresubmitError(
2074 'android.widget.Toast usage is detected. Android toasts use hardware'
2075 ' acceleration, and can be\ncostly on low-end devices. Please use'
2076 ' org.chromium.ui.widget.Toast instead.\n'
2077 'Contact [email protected] if you have any questions.',
2078 errors))
2079
2080 return results
2081
2082
dgnaa68d5e2015-06-10 10:08:222083def _CheckAndroidCrLogUsage(input_api, output_api):
2084 """Checks that new logs using org.chromium.base.Log:
2085 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:512086 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:222087 """
pkotwicza1dd0b002016-05-16 14:41:042088
torne89540622017-03-24 19:41:302089 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:042090 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:302091 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:042092 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:302093 # WebView license viewer code cannot depend on //base; used in stub APK.
2094 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
2095 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:042096 ]
2097
dgnaa68d5e2015-06-10 10:08:222098 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:122099 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
2100 class_in_base_pattern = input_api.re.compile(
2101 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
2102 has_some_log_import_pattern = input_api.re.compile(
2103 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222104 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:122105 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:222106 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:512107 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:222108 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222109
Vincent Scheib16d7b272015-09-15 18:09:072110 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:222111 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:042112 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
2113 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:122114
dgnaa68d5e2015-06-10 10:08:222115 tag_decl_errors = []
2116 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:122117 tag_errors = []
dgn38736db2015-09-18 19:20:512118 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:122119 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:222120
2121 for f in input_api.AffectedSourceFiles(sources):
2122 file_content = input_api.ReadFile(f)
2123 has_modified_logs = False
2124
2125 # Per line checks
dgn87d9fb62015-06-12 09:15:122126 if (cr_log_import_pattern.search(file_content) or
2127 (class_in_base_pattern.search(file_content) and
2128 not has_some_log_import_pattern.search(file_content))):
2129 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:222130 for line_num, line in f.ChangedContents():
2131
2132 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:122133 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:222134 if match:
2135 has_modified_logs = True
2136
2137 # Make sure it uses "TAG"
2138 if not match.group('tag') == 'TAG':
2139 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:122140 else:
2141 # Report non cr Log function calls in changed lines
2142 for line_num, line in f.ChangedContents():
2143 if log_call_pattern.search(line):
2144 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:222145
2146 # Per file checks
2147 if has_modified_logs:
2148 # Make sure the tag is using the "cr" prefix and is not too long
2149 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:512150 tag_name = match.group('name') if match else None
2151 if not tag_name:
dgnaa68d5e2015-06-10 10:08:222152 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512153 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:222154 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512155 elif '.' in tag_name:
2156 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:222157
2158 results = []
2159 if tag_decl_errors:
2160 results.append(output_api.PresubmitPromptWarning(
2161 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:512162 '"private static final String TAG = "<package tag>".\n'
2163 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222164 tag_decl_errors))
2165
2166 if tag_length_errors:
2167 results.append(output_api.PresubmitError(
2168 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:512169 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222170 tag_length_errors))
2171
2172 if tag_errors:
2173 results.append(output_api.PresubmitPromptWarning(
2174 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
2175 tag_errors))
2176
dgn87d9fb62015-06-12 09:15:122177 if util_log_errors:
dgn4401aa52015-04-29 16:26:172178 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:122179 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
2180 util_log_errors))
2181
dgn38736db2015-09-18 19:20:512182 if tag_with_dot_errors:
2183 results.append(output_api.PresubmitPromptWarning(
2184 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
2185 tag_with_dot_errors))
2186
dgn4401aa52015-04-29 16:26:172187 return results
2188
2189
Yoland Yanb92fa522017-08-28 17:37:062190def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
2191 """Checks that junit.framework.* is no longer used."""
2192 deprecated_junit_framework_pattern = input_api.re.compile(
2193 r'^import junit\.framework\..*;',
2194 input_api.re.MULTILINE)
2195 sources = lambda x: input_api.FilterSourceFile(
2196 x, white_list=(r'.*\.java$',), black_list=None)
2197 errors = []
2198 for f in input_api.AffectedFiles(sources):
2199 for line_num, line in f.ChangedContents():
2200 if deprecated_junit_framework_pattern.search(line):
2201 errors.append("%s:%d" % (f.LocalPath(), line_num))
2202
2203 results = []
2204 if errors:
2205 results.append(output_api.PresubmitError(
2206 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
2207 '(org.junit.*) from //third_party/junit. Contact [email protected]'
2208 ' if you have any question.', errors))
2209 return results
2210
2211
2212def _CheckAndroidTestJUnitInheritance(input_api, output_api):
2213 """Checks that if new Java test classes have inheritance.
2214 Either the new test class is JUnit3 test or it is a JUnit4 test class
2215 with a base class, either case is undesirable.
2216 """
2217 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
2218
2219 sources = lambda x: input_api.FilterSourceFile(
2220 x, white_list=(r'.*Test\.java$',), black_list=None)
2221 errors = []
2222 for f in input_api.AffectedFiles(sources):
2223 if not f.OldContents():
2224 class_declaration_start_flag = False
2225 for line_num, line in f.ChangedContents():
2226 if class_declaration_pattern.search(line):
2227 class_declaration_start_flag = True
2228 if class_declaration_start_flag and ' extends ' in line:
2229 errors.append('%s:%d' % (f.LocalPath(), line_num))
2230 if '{' in line:
2231 class_declaration_start_flag = False
2232
2233 results = []
2234 if errors:
2235 results.append(output_api.PresubmitPromptWarning(
2236 'The newly created files include Test classes that inherits from base'
2237 ' class. Please do not use inheritance in JUnit4 tests or add new'
2238 ' JUnit3 tests. Contact [email protected] if you have any'
2239 ' questions.', errors))
2240 return results
2241
yolandyan45001472016-12-21 21:12:422242def _CheckAndroidTestAnnotationUsage(input_api, output_api):
2243 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
2244 deprecated_annotation_import_pattern = input_api.re.compile(
2245 r'^import android\.test\.suitebuilder\.annotation\..*;',
2246 input_api.re.MULTILINE)
2247 sources = lambda x: input_api.FilterSourceFile(
2248 x, white_list=(r'.*\.java$',), black_list=None)
2249 errors = []
2250 for f in input_api.AffectedFiles(sources):
2251 for line_num, line in f.ChangedContents():
2252 if deprecated_annotation_import_pattern.search(line):
2253 errors.append("%s:%d" % (f.LocalPath(), line_num))
2254
2255 results = []
2256 if errors:
2257 results.append(output_api.PresubmitError(
2258 'Annotations in android.test.suitebuilder.annotation have been'
2259 ' deprecated since API level 24. Please use android.support.test.filters'
2260 ' from //third_party/android_support_test_runner:runner_java instead.'
2261 ' Contact [email protected] if you have any questions.', errors))
2262 return results
2263
2264
agrieve7b6479d82015-10-07 14:24:222265def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
2266 """Checks if MDPI assets are placed in a correct directory."""
2267 file_filter = lambda f: (f.LocalPath().endswith('.png') and
2268 ('/res/drawable/' in f.LocalPath() or
2269 '/res/drawable-ldrtl/' in f.LocalPath()))
2270 errors = []
2271 for f in input_api.AffectedFiles(include_deletes=False,
2272 file_filter=file_filter):
2273 errors.append(' %s' % f.LocalPath())
2274
2275 results = []
2276 if errors:
2277 results.append(output_api.PresubmitError(
2278 'MDPI assets should be placed in /res/drawable-mdpi/ or '
2279 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
2280 '/res/drawable-ldrtl/.\n'
2281 'Contact [email protected] if you have questions.', errors))
2282 return results
2283
2284
Nate Fischer535972b2017-09-16 01:06:182285def _CheckAndroidWebkitImports(input_api, output_api):
2286 """Checks that code uses org.chromium.base.Callback instead of
2287 android.widget.ValueCallback except in the WebView glue layer.
2288 """
2289 valuecallback_import_pattern = input_api.re.compile(
2290 r'^import android\.webkit\.ValueCallback;$')
2291
2292 errors = []
2293
2294 sources = lambda affected_file: input_api.FilterSourceFile(
2295 affected_file,
2296 black_list=(_EXCLUDED_PATHS +
2297 _TEST_CODE_EXCLUDED_PATHS +
2298 input_api.DEFAULT_BLACK_LIST +
2299 (r'^android_webview[\\\/]glue[\\\/].*',)),
2300 white_list=(r'.*\.java$',))
2301
2302 for f in input_api.AffectedSourceFiles(sources):
2303 for line_num, line in f.ChangedContents():
2304 if valuecallback_import_pattern.search(line):
2305 errors.append("%s:%d" % (f.LocalPath(), line_num))
2306
2307 results = []
2308
2309 if errors:
2310 results.append(output_api.PresubmitError(
2311 'android.webkit.ValueCallback usage is detected outside of the glue'
2312 ' layer. To stay compatible with the support library, android.webkit.*'
2313 ' classes should only be used inside the glue layer and'
2314 ' org.chromium.base.Callback should be used instead.',
2315 errors))
2316
2317 return results
2318
2319
agrievef32bcc72016-04-04 14:57:402320class PydepsChecker(object):
2321 def __init__(self, input_api, pydeps_files):
2322 self._file_cache = {}
2323 self._input_api = input_api
2324 self._pydeps_files = pydeps_files
2325
2326 def _LoadFile(self, path):
2327 """Returns the list of paths within a .pydeps file relative to //."""
2328 if path not in self._file_cache:
2329 with open(path) as f:
2330 self._file_cache[path] = f.read()
2331 return self._file_cache[path]
2332
2333 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
2334 """Returns an interable of paths within the .pydep, relativized to //."""
2335 os_path = self._input_api.os_path
2336 pydeps_dir = os_path.dirname(pydeps_path)
2337 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2338 if not l.startswith('*'))
2339 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2340
2341 def _CreateFilesToPydepsMap(self):
2342 """Returns a map of local_path -> list_of_pydeps."""
2343 ret = {}
2344 for pydep_local_path in self._pydeps_files:
2345 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2346 ret.setdefault(path, []).append(pydep_local_path)
2347 return ret
2348
2349 def ComputeAffectedPydeps(self):
2350 """Returns an iterable of .pydeps files that might need regenerating."""
2351 affected_pydeps = set()
2352 file_to_pydeps_map = None
2353 for f in self._input_api.AffectedFiles(include_deletes=True):
2354 local_path = f.LocalPath()
2355 if local_path == 'DEPS':
2356 return self._pydeps_files
2357 elif local_path.endswith('.pydeps'):
2358 if local_path in self._pydeps_files:
2359 affected_pydeps.add(local_path)
2360 elif local_path.endswith('.py'):
2361 if file_to_pydeps_map is None:
2362 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2363 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2364 return affected_pydeps
2365
2366 def DetermineIfStale(self, pydeps_path):
2367 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412368 import difflib
John Budorick47ca3fe2018-02-10 00:53:102369 import os
2370
agrievef32bcc72016-04-04 14:57:402371 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2372 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:102373 env = dict(os.environ)
2374 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:402375 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:102376 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412377 old_contents = old_pydeps_data[2:]
2378 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402379 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412380 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402381
2382
2383def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2384 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:402385 # This check is for Python dependency lists (.pydeps files), and involves
2386 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
2387 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:282388 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002389 return []
Mostyn Bramley-Moore6b427322017-12-21 22:11:022390 # TODO(agrieve): Update when there's a better way to detect
2391 # this: crbug.com/570091
agrievef32bcc72016-04-04 14:57:402392 is_android = input_api.os_path.exists('third_party/android_tools')
2393 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2394 results = []
2395 # First, check for new / deleted .pydeps.
2396 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:032397 # Check whether we are running the presubmit check for a file in src.
2398 # f.LocalPath is relative to repo (src, or internal repo).
2399 # os_path.exists is relative to src repo.
2400 # Therefore if os_path.exists is true, it means f.LocalPath is relative
2401 # to src and we can conclude that the pydeps is in src.
2402 if input_api.os_path.exists(f.LocalPath()):
2403 if f.LocalPath().endswith('.pydeps'):
2404 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2405 results.append(output_api.PresubmitError(
2406 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2407 'remove %s' % f.LocalPath()))
2408 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2409 results.append(output_api.PresubmitError(
2410 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2411 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:402412
2413 if results:
2414 return results
2415
2416 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2417
2418 for pydep_path in checker.ComputeAffectedPydeps():
2419 try:
phajdan.jr0d9878552016-11-04 10:49:412420 result = checker.DetermineIfStale(pydep_path)
2421 if result:
2422 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402423 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412424 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2425 'To regenerate, run:\n\n %s' %
2426 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402427 except input_api.subprocess.CalledProcessError as error:
2428 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2429 long_text=error.output)]
2430
2431 return results
2432
2433
glidere61efad2015-02-18 17:39:432434def _CheckSingletonInHeaders(input_api, output_api):
2435 """Checks to make sure no header files have |Singleton<|."""
2436 def FileFilter(affected_file):
2437 # It's ok for base/memory/singleton.h to have |Singleton<|.
2438 black_list = (_EXCLUDED_PATHS +
2439 input_api.DEFAULT_BLACK_LIST +
Michael Warrese4451492018-03-07 04:42:472440 (r"^base[\\\/]memory[\\\/]singleton\.h$",
2441 r"^net[\\\/]quic[\\\/]platform[\\\/]impl[\\\/]"
2442 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:432443 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2444
sergeyu34d21222015-09-16 00:11:442445 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432446 files = []
2447 for f in input_api.AffectedSourceFiles(FileFilter):
2448 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2449 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2450 contents = input_api.ReadFile(f)
2451 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242452 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432453 pattern.search(line)):
2454 files.append(f)
2455 break
2456
2457 if files:
yolandyandaabc6d2016-04-18 18:29:392458 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442459 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432460 'Please move them to an appropriate source file so that the ' +
2461 'template gets instantiated in a single compilation unit.',
2462 files) ]
2463 return []
2464
2465
[email protected]fd20b902014-05-09 02:14:532466_DEPRECATED_CSS = [
2467 # Values
2468 ( "-webkit-box", "flex" ),
2469 ( "-webkit-inline-box", "inline-flex" ),
2470 ( "-webkit-flex", "flex" ),
2471 ( "-webkit-inline-flex", "inline-flex" ),
2472 ( "-webkit-min-content", "min-content" ),
2473 ( "-webkit-max-content", "max-content" ),
2474
2475 # Properties
2476 ( "-webkit-background-clip", "background-clip" ),
2477 ( "-webkit-background-origin", "background-origin" ),
2478 ( "-webkit-background-size", "background-size" ),
2479 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442480 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532481
2482 # Functions
2483 ( "-webkit-gradient", "gradient" ),
2484 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2485 ( "-webkit-linear-gradient", "linear-gradient" ),
2486 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2487 ( "-webkit-radial-gradient", "radial-gradient" ),
2488 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2489]
2490
dbeam1ec68ac2016-12-15 05:22:242491def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532492 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252493 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342494 documentation and iOS CSS for dom distiller
2495 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252496 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532497 results = []
dbeam070cfe62014-10-22 06:44:022498 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252499 black_list = (_EXCLUDED_PATHS +
2500 _TEST_CODE_EXCLUDED_PATHS +
2501 input_api.DEFAULT_BLACK_LIST +
2502 (r"^chrome/common/extensions/docs",
2503 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342504 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442505 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252506 r"^native_client_sdk"))
2507 file_filter = lambda f: input_api.FilterSourceFile(
2508 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532509 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2510 for line_num, line in fpath.ChangedContents():
2511 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022512 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532513 results.append(output_api.PresubmitError(
2514 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2515 (fpath.LocalPath(), line_num, deprecated_value, value)))
2516 return results
2517
mohan.reddyf21db962014-10-16 12:26:472518
dbeam070cfe62014-10-22 06:44:022519_DEPRECATED_JS = [
2520 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2521 ( "__defineGetter__", "Object.defineProperty" ),
2522 ( "__defineSetter__", "Object.defineProperty" ),
2523]
2524
dbeam1ec68ac2016-12-15 05:22:242525def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022526 """Make sure that we don't use deprecated JS in Chrome code."""
2527 results = []
2528 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2529 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2530 input_api.DEFAULT_BLACK_LIST)
2531 file_filter = lambda f: input_api.FilterSourceFile(
2532 f, white_list=file_inclusion_pattern, black_list=black_list)
2533 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2534 for lnum, line in fpath.ChangedContents():
2535 for (deprecated, replacement) in _DEPRECATED_JS:
2536 if deprecated in line:
2537 results.append(output_api.PresubmitError(
2538 "%s:%d: Use of deprecated JS %s, use %s instead" %
2539 (fpath.LocalPath(), lnum, deprecated, replacement)))
2540 return results
2541
dpapadd651231d82017-07-21 02:44:472542def _CheckForRiskyJsArrowFunction(line_number, line):
2543 if ' => ' in line:
2544 return "line %d, is using an => (arrow) function\n %s\n" % (
2545 line_number, line)
2546 return ''
2547
2548def _CheckForRiskyJsConstLet(input_api, line_number, line):
2549 if input_api.re.match('^\s*(const|let)\s', line):
2550 return "line %d, is using const/let keyword\n %s\n" % (
2551 line_number, line)
2552 return ''
dbeam070cfe62014-10-22 06:44:022553
dbeam1ec68ac2016-12-15 05:22:242554def _CheckForRiskyJsFeatures(input_api, output_api):
2555 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002556 # 'ui/webui/resources/cr_components are not allowed on ios'
2557 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572558 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002559 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472560 results = []
dbeam1ec68ac2016-12-15 05:22:242561 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472562 arrow_error_lines = []
2563 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242564 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472565 arrow_error_lines += filter(None, [
2566 _CheckForRiskyJsArrowFunction(lnum, line),
2567 ])
dbeam1ec68ac2016-12-15 05:22:242568
dpapadd651231d82017-07-21 02:44:472569 const_let_error_lines += filter(None, [
2570 _CheckForRiskyJsConstLet(input_api, lnum, line),
2571 ])
dbeam1ec68ac2016-12-15 05:22:242572
dpapadd651231d82017-07-21 02:44:472573 if arrow_error_lines:
2574 arrow_error_lines = map(
2575 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2576 results.append(
2577 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2578"""
2579Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242580%s
2581Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2582https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472583""" % f.LocalPath()
2584 ])))
dbeam1ec68ac2016-12-15 05:22:242585
dpapadd651231d82017-07-21 02:44:472586 if const_let_error_lines:
2587 const_let_error_lines = map(
2588 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2589 results.append(
2590 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2591"""
2592Use of const/let keywords detected in:
2593%s
2594Please ensure your code does not run on iOS9 because const/let is not fully
2595supported.
2596https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2597https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2598""" % f.LocalPath()
2599 ])))
2600
2601 return results
dbeam1ec68ac2016-12-15 05:22:242602
rlanday6802cf632017-05-30 17:48:362603def _CheckForRelativeIncludes(input_api, output_api):
2604 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2605 import sys
2606 original_sys_path = sys.path
2607 try:
2608 sys.path = sys.path + [input_api.os_path.join(
2609 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2610 from cpp_checker import CppChecker
2611 finally:
2612 # Restore sys.path to what it was before.
2613 sys.path = original_sys_path
2614
2615 bad_files = {}
2616 for f in input_api.AffectedFiles(include_deletes=False):
2617 if (f.LocalPath().startswith('third_party') and
2618 not f.LocalPath().startswith('third_party/WebKit') and
2619 not f.LocalPath().startswith('third_party\\WebKit')):
2620 continue
2621
2622 if not CppChecker.IsCppFile(f.LocalPath()):
2623 continue
2624
Vaclav Brozekd5de76a2018-03-17 07:57:502625 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:362626 if "#include" in line and "../" in line]
2627 if not relative_includes:
2628 continue
2629 bad_files[f.LocalPath()] = relative_includes
2630
2631 if not bad_files:
2632 return []
2633
2634 error_descriptions = []
2635 for file_path, bad_lines in bad_files.iteritems():
2636 error_description = file_path
2637 for line in bad_lines:
2638 error_description += '\n ' + line
2639 error_descriptions.append(error_description)
2640
2641 results = []
2642 results.append(output_api.PresubmitError(
2643 'You added one or more relative #include paths (including "../").\n'
2644 'These shouldn\'t be used because they can be used to include headers\n'
2645 'from code that\'s not correctly specified as a dependency in the\n'
2646 'relevant BUILD.gn file(s).',
2647 error_descriptions))
2648
2649 return results
2650
Takeshi Yoshinoe387aa32017-08-02 13:16:132651
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202652def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2653 if not isinstance(key, ast.Str):
2654 return 'Key at line %d must be a string literal' % key.lineno
2655 if not isinstance(value, ast.Dict):
2656 return 'Value at line %d must be a dict' % value.lineno
2657 if len(value.keys) != 1:
2658 return 'Dict at line %d must have single entry' % value.lineno
2659 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2660 return (
2661 'Entry at line %d must have a string literal \'filepath\' as key' %
2662 value.lineno)
2663 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132664
Takeshi Yoshinoe387aa32017-08-02 13:16:132665
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202666def _CheckWatchlistsEntrySyntax(key, value, ast):
2667 if not isinstance(key, ast.Str):
2668 return 'Key at line %d must be a string literal' % key.lineno
2669 if not isinstance(value, ast.List):
2670 return 'Value at line %d must be a list' % value.lineno
2671 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132672
Takeshi Yoshinoe387aa32017-08-02 13:16:132673
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202674def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2675 mismatch_template = (
2676 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2677 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132678
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202679 i = 0
2680 last_key = ''
2681 while True:
2682 if i >= len(wd_dict.keys):
2683 if i >= len(w_dict.keys):
2684 return None
2685 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2686 elif i >= len(w_dict.keys):
2687 return (
2688 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132689
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202690 wd_key = wd_dict.keys[i]
2691 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132692
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202693 result = _CheckWatchlistDefinitionsEntrySyntax(
2694 wd_key, wd_dict.values[i], ast)
2695 if result is not None:
2696 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132697
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202698 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2699 if result is not None:
2700 return 'Bad entry in WATCHLISTS dict: %s' % result
2701
2702 if wd_key.s != w_key.s:
2703 return mismatch_template % (
2704 '%s at line %d' % (wd_key.s, wd_key.lineno),
2705 '%s at line %d' % (w_key.s, w_key.lineno))
2706
2707 if wd_key.s < last_key:
2708 return (
2709 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2710 (wd_key.lineno, w_key.lineno))
2711 last_key = wd_key.s
2712
2713 i = i + 1
2714
2715
2716def _CheckWATCHLISTSSyntax(expression, ast):
2717 if not isinstance(expression, ast.Expression):
2718 return 'WATCHLISTS file must contain a valid expression'
2719 dictionary = expression.body
2720 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2721 return 'WATCHLISTS file must have single dict with exactly two entries'
2722
2723 first_key = dictionary.keys[0]
2724 first_value = dictionary.values[0]
2725 second_key = dictionary.keys[1]
2726 second_value = dictionary.values[1]
2727
2728 if (not isinstance(first_key, ast.Str) or
2729 first_key.s != 'WATCHLIST_DEFINITIONS' or
2730 not isinstance(first_value, ast.Dict)):
2731 return (
2732 'The first entry of the dict in WATCHLISTS file must be '
2733 'WATCHLIST_DEFINITIONS dict')
2734
2735 if (not isinstance(second_key, ast.Str) or
2736 second_key.s != 'WATCHLISTS' or
2737 not isinstance(second_value, ast.Dict)):
2738 return (
2739 'The second entry of the dict in WATCHLISTS file must be '
2740 'WATCHLISTS dict')
2741
2742 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132743
2744
2745def _CheckWATCHLISTS(input_api, output_api):
2746 for f in input_api.AffectedFiles(include_deletes=False):
2747 if f.LocalPath() == 'WATCHLISTS':
2748 contents = input_api.ReadFile(f, 'r')
2749
2750 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202751 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132752 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202753 # Get an AST tree for it and scan the tree for detailed style checking.
2754 expression = input_api.ast.parse(
2755 contents, filename='WATCHLISTS', mode='eval')
2756 except ValueError as e:
2757 return [output_api.PresubmitError(
2758 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2759 except SyntaxError as e:
2760 return [output_api.PresubmitError(
2761 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2762 except TypeError as e:
2763 return [output_api.PresubmitError(
2764 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132765
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202766 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2767 if result is not None:
2768 return [output_api.PresubmitError(result)]
2769 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132770
2771 return []
2772
2773
dgnaa68d5e2015-06-10 10:08:222774def _AndroidSpecificOnUploadChecks(input_api, output_api):
2775 """Groups checks that target android code."""
2776 results = []
dgnaa68d5e2015-06-10 10:08:222777 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222778 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292779 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062780 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2781 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422782 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182783 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222784 return results
2785
2786
[email protected]22c9bd72011-03-27 16:47:392787def _CommonChecks(input_api, output_api):
2788 """Checks common to both upload and commit."""
2789 results = []
2790 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382791 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542792 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:082793
2794 author = input_api.change.author_email
2795 if author and author not in _KNOWN_ROBOTS:
2796 results.extend(
2797 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
2798
[email protected]55459852011-08-10 15:17:192799 results.extend(
[email protected]760deea2013-12-10 19:33:492800 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:232801 results.extend(
2802 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542803 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182804 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522805 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222806 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442807 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592808 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062809 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122810 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182811 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222812 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302813 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492814 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032815 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492816 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442817 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272818 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072819 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542820 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442821 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392822 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552823 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042824 results.extend(
2825 input_api.canned_checks.CheckChangeHasNoTabs(
2826 input_api,
2827 output_api,
2828 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402829 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162830 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082831 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242832 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2833 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472834 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042835 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:052836 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:142837 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232838 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432839 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402840 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152841 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172842 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502843 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242844 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362845 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132846 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432847 results.extend(input_api.RunTests(
2848 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242849
Vaclav Brozekcdc7defb2018-03-20 09:54:352850 for f in input_api.AffectedFiles():
2851 path, name = input_api.os_path.split(f.LocalPath())
2852 if name == 'PRESUBMIT.py':
2853 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:002854 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
2855 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:072856 # The PRESUBMIT.py file (and the directory containing it) might
2857 # have been affected by being moved or removed, so only try to
2858 # run the tests if they still exist.
2859 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2860 input_api, output_api, full_path,
2861 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392862 return results
[email protected]1f7b4172010-01-28 01:17:342863
[email protected]b337cb5b2011-01-23 21:24:052864
[email protected]b8079ae4a2012-12-05 19:56:492865def _CheckPatchFiles(input_api, output_api):
2866 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2867 if f.LocalPath().endswith(('.orig', '.rej'))]
2868 if problems:
2869 return [output_api.PresubmitError(
2870 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032871 else:
2872 return []
[email protected]b8079ae4a2012-12-05 19:56:492873
2874
Kent Tamura5a8755d2017-06-29 23:37:072875def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212876 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2877 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2878 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072879 include_re = input_api.re.compile(
2880 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2881 extension_re = input_api.re.compile(r'\.[a-z]+$')
2882 errors = []
2883 for f in input_api.AffectedFiles():
2884 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2885 continue
2886 found_line_number = None
2887 found_macro = None
2888 for line_num, line in f.ChangedContents():
2889 match = macro_re.search(line)
2890 if match:
2891 found_line_number = line_num
2892 found_macro = match.group(2)
2893 break
2894 if not found_line_number:
2895 continue
2896
2897 found_include = False
2898 for line in f.NewContents():
2899 if include_re.search(line):
2900 found_include = True
2901 break
2902 if found_include:
2903 continue
2904
2905 if not f.LocalPath().endswith('.h'):
2906 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2907 try:
2908 content = input_api.ReadFile(primary_header_path, 'r')
2909 if include_re.search(content):
2910 continue
2911 except IOError:
2912 pass
2913 errors.append('%s:%d %s macro is used without including build/'
2914 'build_config.h.'
2915 % (f.LocalPath(), found_line_number, found_macro))
2916 if errors:
2917 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2918 return []
2919
2920
[email protected]b00342e7f2013-03-26 16:21:542921def _DidYouMeanOSMacro(bad_macro):
2922 try:
2923 return {'A': 'OS_ANDROID',
2924 'B': 'OS_BSD',
2925 'C': 'OS_CHROMEOS',
2926 'F': 'OS_FREEBSD',
2927 'L': 'OS_LINUX',
2928 'M': 'OS_MACOSX',
2929 'N': 'OS_NACL',
2930 'O': 'OS_OPENBSD',
2931 'P': 'OS_POSIX',
2932 'S': 'OS_SOLARIS',
2933 'W': 'OS_WIN'}[bad_macro[3].upper()]
2934 except KeyError:
2935 return ''
2936
2937
2938def _CheckForInvalidOSMacrosInFile(input_api, f):
2939 """Check for sensible looking, totally invalid OS macros."""
2940 preprocessor_statement = input_api.re.compile(r'^\s*#')
2941 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2942 results = []
2943 for lnum, line in f.ChangedContents():
2944 if preprocessor_statement.search(line):
2945 for match in os_macro.finditer(line):
2946 if not match.group(1) in _VALID_OS_MACROS:
2947 good = _DidYouMeanOSMacro(match.group(1))
2948 did_you_mean = ' (did you mean %s?)' % good if good else ''
2949 results.append(' %s:%d %s%s' % (f.LocalPath(),
2950 lnum,
2951 match.group(1),
2952 did_you_mean))
2953 return results
2954
2955
2956def _CheckForInvalidOSMacros(input_api, output_api):
2957 """Check all affected files for invalid OS macros."""
2958 bad_macros = []
2959 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472960 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542961 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2962
2963 if not bad_macros:
2964 return []
2965
2966 return [output_api.PresubmitError(
2967 'Possibly invalid OS macro[s] found. Please fix your code\n'
2968 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2969
lliabraa35bab3932014-10-01 12:16:442970
2971def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2972 """Check all affected files for invalid "if defined" macros."""
2973 ALWAYS_DEFINED_MACROS = (
2974 "TARGET_CPU_PPC",
2975 "TARGET_CPU_PPC64",
2976 "TARGET_CPU_68K",
2977 "TARGET_CPU_X86",
2978 "TARGET_CPU_ARM",
2979 "TARGET_CPU_MIPS",
2980 "TARGET_CPU_SPARC",
2981 "TARGET_CPU_ALPHA",
2982 "TARGET_IPHONE_SIMULATOR",
2983 "TARGET_OS_EMBEDDED",
2984 "TARGET_OS_IPHONE",
2985 "TARGET_OS_MAC",
2986 "TARGET_OS_UNIX",
2987 "TARGET_OS_WIN32",
2988 )
2989 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2990 results = []
2991 for lnum, line in f.ChangedContents():
2992 for match in ifdef_macro.finditer(line):
2993 if match.group(1) in ALWAYS_DEFINED_MACROS:
2994 always_defined = ' %s is always defined. ' % match.group(1)
2995 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2996 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2997 lnum,
2998 always_defined,
2999 did_you_mean))
3000 return results
3001
3002
3003def _CheckForInvalidIfDefinedMacros(input_api, output_api):
3004 """Check all affected files for invalid "if defined" macros."""
3005 bad_macros = []
3006 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:213007 if f.LocalPath().startswith('third_party/sqlite/'):
3008 continue
lliabraa35bab3932014-10-01 12:16:443009 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
3010 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
3011
3012 if not bad_macros:
3013 return []
3014
3015 return [output_api.PresubmitError(
3016 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
3017 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
3018 bad_macros)]
3019
3020
mlamouria82272622014-09-16 18:45:043021def _CheckForIPCRules(input_api, output_api):
3022 """Check for same IPC rules described in
3023 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
3024 """
3025 base_pattern = r'IPC_ENUM_TRAITS\('
3026 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
3027 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
3028
3029 problems = []
3030 for f in input_api.AffectedSourceFiles(None):
3031 local_path = f.LocalPath()
3032 if not local_path.endswith('.h'):
3033 continue
3034 for line_number, line in f.ChangedContents():
3035 if inclusion_pattern.search(line) and not comment_pattern.search(line):
3036 problems.append(
3037 '%s:%d\n %s' % (local_path, line_number, line.strip()))
3038
3039 if problems:
3040 return [output_api.PresubmitPromptWarning(
3041 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
3042 else:
3043 return []
3044
[email protected]b00342e7f2013-03-26 16:21:543045
Stephen Martinis97a394142018-06-07 23:06:053046def _CheckForLongPathnames(input_api, output_api):
3047 """Check to make sure no files being submitted have long paths.
3048 This causes issues on Windows.
3049 """
3050 problems = []
3051 for f in input_api.AffectedSourceFiles(None):
3052 local_path = f.LocalPath()
3053 # Windows has a path limit of 260 characters. Limit path length to 200 so
3054 # that we have some extra for the prefix on dev machines and the bots.
3055 if len(local_path) > 200:
3056 problems.append(local_path)
3057
3058 if problems:
3059 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
3060 else:
3061 return []
3062
3063
Daniel Bratell8ba52722018-03-02 16:06:143064def _CheckForIncludeGuards(input_api, output_api):
3065 """Check that header files have proper guards against multiple inclusion.
3066 If a file should not have such guards (and it probably should) then it
3067 should include the string "no-include-guard-because-multiply-included".
3068 """
Daniel Bratell6a75baef62018-06-04 10:04:453069 def is_chromium_header_file(f):
3070 # We only check header files under the control of the Chromium
3071 # project. That is, those outside third_party apart from
3072 # third_party/blink.
3073 file_with_path = input_api.os_path.normpath(f.LocalPath())
3074 return (file_with_path.endswith('.h') and
3075 (not file_with_path.startswith('third_party') or
3076 file_with_path.startswith(
3077 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:143078
3079 def replace_special_with_underscore(string):
3080 return input_api.re.sub(r'[\\/.-]', '_', string)
3081
3082 errors = []
3083
Daniel Bratell6a75baef62018-06-04 10:04:453084 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:143085 guard_name = None
3086 guard_line_number = None
3087 seen_guard_end = False
3088
3089 file_with_path = input_api.os_path.normpath(f.LocalPath())
3090 base_file_name = input_api.os_path.splitext(
3091 input_api.os_path.basename(file_with_path))[0]
3092 upper_base_file_name = base_file_name.upper()
3093
3094 expected_guard = replace_special_with_underscore(
3095 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:143096
3097 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:573098 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
3099 # are too many (1000+) files with slight deviations from the
3100 # coding style. The most important part is that the include guard
3101 # is there, and that it's unique, not the name so this check is
3102 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:143103 #
3104 # As code becomes more uniform, this could be made stricter.
3105
3106 guard_name_pattern_list = [
3107 # Anything with the right suffix (maybe with an extra _).
3108 r'\w+_H__?',
3109
Daniel Bratell39b5b062018-05-16 18:09:573110 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:143111 r'\w+_h',
3112
3113 # Anything including the uppercase name of the file.
3114 r'\w*' + input_api.re.escape(replace_special_with_underscore(
3115 upper_base_file_name)) + r'\w*',
3116 ]
3117 guard_name_pattern = '|'.join(guard_name_pattern_list)
3118 guard_pattern = input_api.re.compile(
3119 r'#ifndef\s+(' + guard_name_pattern + ')')
3120
3121 for line_number, line in enumerate(f.NewContents()):
3122 if 'no-include-guard-because-multiply-included' in line:
3123 guard_name = 'DUMMY' # To not trigger check outside the loop.
3124 break
3125
3126 if guard_name is None:
3127 match = guard_pattern.match(line)
3128 if match:
3129 guard_name = match.group(1)
3130 guard_line_number = line_number
3131
Daniel Bratell39b5b062018-05-16 18:09:573132 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:453133 # don't match the chromium style guide, but new files should
3134 # get it right.
3135 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:573136 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:143137 errors.append(output_api.PresubmitPromptWarning(
3138 'Header using the wrong include guard name %s' % guard_name,
3139 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Daniel Bratell39b5b062018-05-16 18:09:573140 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:143141 else:
3142 # The line after #ifndef should have a #define of the same name.
3143 if line_number == guard_line_number + 1:
3144 expected_line = '#define %s' % guard_name
3145 if line != expected_line:
3146 errors.append(output_api.PresubmitPromptWarning(
3147 'Missing "%s" for include guard' % expected_line,
3148 ['%s:%d' % (f.LocalPath(), line_number + 1)],
3149 'Expected: %r\nGot: %r' % (expected_line, line)))
3150
3151 if not seen_guard_end and line == '#endif // %s' % guard_name:
3152 seen_guard_end = True
3153 elif seen_guard_end:
3154 if line.strip() != '':
3155 errors.append(output_api.PresubmitPromptWarning(
3156 'Include guard %s not covering the whole file' % (
3157 guard_name), [f.LocalPath()]))
3158 break # Nothing else to check and enough to warn once.
3159
3160 if guard_name is None:
3161 errors.append(output_api.PresubmitPromptWarning(
3162 'Missing include guard %s' % expected_guard,
3163 [f.LocalPath()],
3164 'Missing include guard in %s\n'
3165 'Recommended name: %s\n'
3166 'This check can be disabled by having the string\n'
3167 'no-include-guard-because-multiply-included in the header.' %
3168 (f.LocalPath(), expected_guard)))
3169
3170 return errors
3171
3172
mostynbb639aca52015-01-07 20:31:233173def _CheckForWindowsLineEndings(input_api, output_api):
3174 """Check source code and known ascii text files for Windows style line
3175 endings.
3176 """
earthdok1b5e0ee2015-03-10 15:19:103177 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:233178
3179 file_inclusion_pattern = (
3180 known_text_files,
3181 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3182 )
3183
mostynbb639aca52015-01-07 20:31:233184 problems = []
Andrew Grieve933d12e2017-10-30 20:22:533185 source_file_filter = lambda f: input_api.FilterSourceFile(
3186 f, white_list=file_inclusion_pattern, black_list=None)
3187 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:503188 include_file = False
3189 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:233190 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:503191 include_file = True
3192 if include_file:
3193 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:233194
3195 if problems:
3196 return [output_api.PresubmitPromptWarning('Are you sure that you want '
3197 'these files to contain Windows style line endings?\n' +
3198 '\n'.join(problems))]
3199
3200 return []
3201
3202
Vaclav Brozekd5de76a2018-03-17 07:57:503203def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:133204 """Checks that all source files use SYSLOG properly."""
3205 syslog_files = []
3206 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:563207 for line_number, line in f.ChangedContents():
3208 if 'SYSLOG' in line:
3209 syslog_files.append(f.LocalPath() + ':' + str(line_number))
3210
pastarmovj89f7ee12016-09-20 14:58:133211 if syslog_files:
3212 return [output_api.PresubmitPromptWarning(
3213 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
3214 ' calls.\nFiles to check:\n', items=syslog_files)]
3215 return []
3216
3217
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193218def _CheckCrbugLinksHaveHttps(input_api, output_api):
Miguel Casas68bdb652017-12-19 16:29:093219 """Checks that crbug(.com) links are correctly prefixed by https://,
3220 unless they come in the accepted form TODO(crbug.com/...)
3221 """
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193222 white_list = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3223 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS)
3224 sources = lambda f: input_api.FilterSourceFile(
3225 f, white_list=white_list, black_list=black_list)
3226
3227 pattern = input_api.re.compile(r'//.*(?<!:\/\/)crbug[.com]*')
Miguel Casas68bdb652017-12-19 16:29:093228 accepted_pattern = input_api.re.compile(r'//.*TODO\(crbug[.com]*');
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193229 problems = []
3230 for f in input_api.AffectedSourceFiles(sources):
3231 for line_num, line in f.ChangedContents():
Miguel Casas68bdb652017-12-19 16:29:093232 if pattern.search(line) and not accepted_pattern.search(line):
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193233 problems.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
3234
3235 if problems:
3236 return [output_api.PresubmitPromptWarning(
3237 'Found unprefixed crbug.com URL(s), consider prepending https://\n'+
3238 '\n'.join(problems))]
3239 return []
3240
3241
[email protected]1f7b4172010-01-28 01:17:343242def CheckChangeOnUpload(input_api, output_api):
3243 results = []
3244 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:473245 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:283246 results.extend(
jam93a6ee792017-02-08 23:59:223247 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:193248 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:223249 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:133250 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:163251 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193252 results.extend(_CheckCrbugLinksHaveHttps(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:533253 results.extend(_CheckUniquePtr(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543254 return results
[email protected]ca8d1982009-02-19 16:33:123255
3256
[email protected]1bfb8322014-04-23 01:02:413257def GetTryServerMasterForBot(bot):
3258 """Returns the Try Server master for the given bot.
3259
[email protected]0bb112362014-07-26 04:38:323260 It tries to guess the master from the bot name, but may still fail
3261 and return None. There is no longer a default master.
3262 """
3263 # Potentially ambiguous bot names are listed explicitly.
3264 master_map = {
tandriie5587792016-07-14 00:34:503265 'chromium_presubmit': 'master.tryserver.chromium.linux',
3266 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:413267 }
[email protected]0bb112362014-07-26 04:38:323268 master = master_map.get(bot)
3269 if not master:
wnwen4fbaab82016-05-25 12:54:363270 if 'android' in bot:
tandriie5587792016-07-14 00:34:503271 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:363272 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:503273 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:323274 elif 'win' in bot:
tandriie5587792016-07-14 00:34:503275 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:323276 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:503277 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:323278 return master
[email protected]1bfb8322014-04-23 01:02:413279
3280
[email protected]ca8d1982009-02-19 16:33:123281def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:543282 results = []
[email protected]1f7b4172010-01-28 01:17:343283 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543284 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:273285 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:343286 input_api,
3287 output_api,
[email protected]2fdd1f362013-01-16 03:56:033288 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:273289
jam93a6ee792017-02-08 23:59:223290 results.extend(
3291 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:543292 results.extend(input_api.canned_checks.CheckChangeHasBugField(
3293 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:413294 results.extend(input_api.canned_checks.CheckChangeHasDescription(
3295 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543296 return results