blob: 48493fcf789f1c187def172ace991aa4eb64e164 [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
182
183_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20184 # Make sure that gtest's FRIEND_TEST() macro is not used; the
185 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30186 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20187 (
thomasandersone7caaa9b2017-03-29 19:22:53188 r'\bNULL\b',
189 (
190 'New code should not use NULL. Use nullptr instead.',
191 ),
192 True,
193 (),
194 ),
195 (
[email protected]23e6cbc2012-06-16 18:51:20196 'FRIEND_TEST(',
197 (
[email protected]e3c945502012-06-26 20:01:49198 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20199 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
200 ),
201 False,
[email protected]7345da02012-11-27 14:31:49202 (),
[email protected]23e6cbc2012-06-16 18:51:20203 ),
204 (
thomasanderson4b569052016-09-14 20:15:53205 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
206 (
207 'Chrome clients wishing to select events on X windows should use',
208 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
209 'you are selecting events from the GPU process, or if you are using',
210 'an XDisplay other than gfx::GetXDisplay().',
211 ),
212 True,
213 (
214 r"^ui[\\\/]gl[\\\/].*\.cc$",
215 r"^media[\\\/]gpu[\\\/].*\.cc$",
216 r"^gpu[\\\/].*\.cc$",
217 ),
218 ),
219 (
thomasandersone043e3ce2017-06-08 00:43:20220 r'XInternAtom|xcb_intern_atom',
221 (
thomasanderson11aa41d2017-06-08 22:22:38222 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20223 ),
224 True,
225 (
thomasanderson11aa41d2017-06-08 22:22:38226 r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$",
227 r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20228 r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$",
229 ),
230 ),
231 (
tomhudsone2c14d552016-05-26 17:07:46232 'setMatrixClip',
233 (
234 'Overriding setMatrixClip() is prohibited; ',
235 'the base function is deprecated. ',
236 ),
237 True,
238 (),
239 ),
240 (
[email protected]52657f62013-05-20 05:30:31241 'SkRefPtr',
242 (
243 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22244 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31245 ),
246 True,
247 (),
248 ),
249 (
250 'SkAutoRef',
251 (
252 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22253 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31254 ),
255 True,
256 (),
257 ),
258 (
259 'SkAutoTUnref',
260 (
261 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22262 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31263 ),
264 True,
265 (),
266 ),
267 (
268 'SkAutoUnref',
269 (
270 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
271 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22272 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31273 ),
274 True,
275 (),
276 ),
[email protected]d89eec82013-12-03 14:10:59277 (
278 r'/HANDLE_EINTR\(.*close',
279 (
280 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
281 'descriptor will be closed, and it is incorrect to retry the close.',
282 'Either call close directly and ignore its return value, or wrap close',
283 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
284 ),
285 True,
286 (),
287 ),
288 (
289 r'/IGNORE_EINTR\((?!.*close)',
290 (
291 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
292 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
293 ),
294 True,
295 (
296 # Files that #define IGNORE_EINTR.
297 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
298 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
299 ),
300 ),
[email protected]ec5b3f02014-04-04 18:43:43301 (
302 r'/v8::Extension\(',
303 (
304 'Do not introduce new v8::Extensions into the code base, use',
305 'gin::Wrappable instead. See http://crbug.com/334679',
306 ),
307 True,
[email protected]f55c90ee62014-04-12 00:50:03308 (
joaodasilva718f87672014-08-30 09:25:49309 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03310 ),
[email protected]ec5b3f02014-04-04 18:43:43311 ),
skyostilf9469f72015-04-20 10:38:52312 (
jame2d1a952016-04-02 00:27:10313 '#pragma comment(lib,',
314 (
315 'Specify libraries to link with in build files and not in the source.',
316 ),
317 True,
318 (),
319 ),
fdorayc4ac18d2017-05-01 21:39:59320 (
gabd52c912a2017-05-11 04:15:59321 'base::SequenceChecker',
322 (
323 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
324 ),
325 False,
326 (),
327 ),
328 (
329 'base::ThreadChecker',
330 (
331 'Consider using THREAD_CHECKER macros instead of the class directly.',
332 ),
333 False,
334 (),
335 ),
dbeamb6f4fde2017-06-15 04:03:06336 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06337 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
338 (
339 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
340 'deprecated (http://crbug.com/634507). Please avoid converting away',
341 'from the Time types in Chromium code, especially if any math is',
342 'being done on time values. For interfacing with platform/library',
343 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
344 'type converter methods instead. For faking TimeXXX values (for unit',
345 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
346 'other use cases, please contact base/time/OWNERS.',
347 ),
348 False,
349 (),
350 ),
351 (
dbeamb6f4fde2017-06-15 04:03:06352 'CallJavascriptFunctionUnsafe',
353 (
354 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
355 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
356 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
357 ),
358 False,
359 (
360 r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$',
361 r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$',
362 r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$',
363 ),
364 ),
dskiba1474c2bfd62017-07-20 02:19:24365 (
366 'leveldb::DB::Open',
367 (
368 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
369 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
370 "Chrome's tracing, making their memory usage visible.",
371 ),
372 True,
373 (
374 r'^third_party/leveldatabase/.*\.(cc|h)$',
375 ),
Gabriel Charette0592c3a2017-07-26 12:02:04376 ),
377 (
Chris Mumfordc38afb62017-10-09 17:55:08378 'leveldb::NewMemEnv',
379 (
380 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
381 'third_party/leveldatabase/leveldb_chrome.h.',
382 ),
383 True,
384 (
385 r'^third_party/leveldatabase/.*\.(cc|h)$',
386 ),
387 ),
388 (
Gabriel Charetted9839bc2017-07-29 14:17:47389 'MessageLoop::QuitWhenIdleClosure',
Gabriel Charette0592c3a2017-07-26 12:02:04390 (
Peter Kasting9e7ccfa52018-02-06 00:01:20391 'MessageLoop::QuitWhenIdleClosure is deprecated. Please use a',
392 'QuitWhenIdleClosure obtained from a specific RunLoop instance.',
Gabriel Charette0592c3a2017-07-26 12:02:04393 ),
Peter Kasting9e7ccfa52018-02-06 00:01:20394 False,
Gabriel Charette0592c3a2017-07-26 12:02:04395 (),
Gabriel Charetted9839bc2017-07-29 14:17:47396 ),
397 (
398 'RunLoop::QuitCurrent',
399 (
Robert Liao64b7ab22017-08-04 23:03:43400 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
401 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47402 ),
403 True,
404 (),
Gabriel Charettea44975052017-08-21 23:14:04405 ),
406 (
407 'base::ScopedMockTimeMessageLoopTaskRunner',
408 (
409 'ScopedMockTimeMessageLoopTaskRunner is deprecated.',
410 ),
411 True,
412 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57413 ),
414 (
415 r'std::regex',
416 (
417 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02418 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57419 ),
420 True,
421 (),
Francois Doray43670e32017-09-27 12:40:38422 ),
423 (
424 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
425 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
426 (
427 'Use the new API in base/threading/thread_restrictions.h.',
428 ),
429 True,
430 (),
431 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38432 (
433 r'/\bbase::Bind\(',
434 (
435 'Please consider using base::Bind{Once,Repeating} instead '
Mostyn Bramley-Moore6b427322017-12-21 22:11:02436 'of base::Bind. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38437 ),
438 False,
439 (),
440 ),
441 (
442 r'/\bbase::Callback<',
443 (
444 'Please consider using base::{Once,Repeating}Callback instead '
Mostyn Bramley-Moore6b427322017-12-21 22:11:02445 'of base::Callback. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38446 ),
447 False,
448 (),
449 ),
450 (
451 r'/\bbase::Closure\b',
452 (
453 'Please consider using base::{Once,Repeating}Closure instead '
Mostyn Bramley-Moore6b427322017-12-21 22:11:02454 'of base::Closure. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38455 ),
456 False,
457 (),
458 ),
Victor Costan3653df62018-02-08 21:38:16459 (
460 'sqlite3_initialize',
461 (
462 'Instead of sqlite3_initialize, depend on //sql, ',
463 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
464 ),
465 True,
466 (
467 r'^sql/initialization\.(cc|h)$',
468 r'^third_party/sqlite/.*\.(c|cc|h)$',
469 ),
470 ),
[email protected]127f18ec2012-06-16 05:05:59471)
472
wnwenbdc444e2016-05-25 13:44:15473
mlamouria82272622014-09-16 18:45:04474_IPC_ENUM_TRAITS_DEPRECATED = (
475 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
476 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
477
Shenghua Zhangbfaa38b82017-11-16 21:58:02478_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
479 r".*[\\\/]BuildHooksAndroidImpl\.java",
480 r".*[\\\/]LicenseContentProvider\.java",
481]
[email protected]127f18ec2012-06-16 05:05:59482
Sean Kau46e29bc2017-08-28 16:31:16483# These paths contain test data and other known invalid JSON files.
484_KNOWN_INVALID_JSON_FILE_PATTERNS = [
485 r'test[\\\/]data[\\\/]',
486 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
487 r'^third_party[\\\/]protobuf[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16488 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Sean Kau46e29bc2017-08-28 16:31:16489]
490
491
[email protected]b00342e7f2013-03-26 16:21:54492_VALID_OS_MACROS = (
493 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08494 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54495 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:12496 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:54497 'OS_BSD',
498 'OS_CAT', # For testing.
499 'OS_CHROMEOS',
500 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37501 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54502 'OS_IOS',
503 'OS_LINUX',
504 'OS_MACOSX',
505 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21506 'OS_NACL_NONSFI',
507 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12508 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54509 'OS_OPENBSD',
510 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37511 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54512 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54513 'OS_WIN',
514)
515
516
agrievef32bcc72016-04-04 14:57:40517_ANDROID_SPECIFIC_PYDEPS_FILES = [
518 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04519 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58520 'build/secondary/third_party/android_platform/'
521 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19522 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40523]
524
wnwenbdc444e2016-05-25 13:44:15525
agrievef32bcc72016-04-04 14:57:40526_GENERIC_PYDEPS_FILES = [
John Chencde89192018-01-27 21:18:40527 'chrome/test/chromedriver/test/run_py_tests.pydeps',
agrievef32bcc72016-04-04 14:57:40528]
529
wnwenbdc444e2016-05-25 13:44:15530
agrievef32bcc72016-04-04 14:57:40531_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
532
533
Eric Boren6fd2b932018-01-25 15:05:08534# Bypass the AUTHORS check for these accounts.
535_KNOWN_ROBOTS = set(
536 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
Eric Borenf7f08f02018-02-08 20:22:52537 for s in ('afdo', 'angle', 'catapult', 'depot-tools', 'nacl', 'pdfium',
538 'skia', 'src-internal', 'webrtc'))
Eric Boren6fd2b932018-01-25 15:05:08539
540
[email protected]55459852011-08-10 15:17:19541def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
542 """Attempts to prevent use of functions intended only for testing in
543 non-testing code. For now this is just a best-effort implementation
544 that ignores header files and may have some false positives. A
545 better implementation would probably need a proper C++ parser.
546 """
547 # We only scan .cc files and the like, as the declaration of
548 # for-testing functions in header files are hard to distinguish from
549 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44550 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19551
jochenc0d4808c2015-07-27 09:25:42552 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19553 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09554 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19555 exclusion_pattern = input_api.re.compile(
556 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
557 base_function_pattern, base_function_pattern))
558
559 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44560 black_list = (_EXCLUDED_PATHS +
561 _TEST_CODE_EXCLUDED_PATHS +
562 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19563 return input_api.FilterSourceFile(
564 affected_file,
565 white_list=(file_inclusion_pattern, ),
566 black_list=black_list)
567
568 problems = []
569 for f in input_api.AffectedSourceFiles(FilterFile):
570 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24571 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03572 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46573 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03574 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19575 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03576 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19577
578 if problems:
[email protected]f7051d52013-04-02 18:31:42579 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03580 else:
581 return []
[email protected]55459852011-08-10 15:17:19582
583
[email protected]10689ca2011-09-02 02:31:54584def _CheckNoIOStreamInHeaders(input_api, output_api):
585 """Checks to make sure no .h files include <iostream>."""
586 files = []
587 pattern = input_api.re.compile(r'^#include\s*<iostream>',
588 input_api.re.MULTILINE)
589 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
590 if not f.LocalPath().endswith('.h'):
591 continue
592 contents = input_api.ReadFile(f)
593 if pattern.search(contents):
594 files.append(f)
595
596 if len(files):
yolandyandaabc6d2016-04-18 18:29:39597 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06598 'Do not #include <iostream> in header files, since it inserts static '
599 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54600 '#include <ostream>. See http://crbug.com/94794',
601 files) ]
602 return []
603
604
[email protected]72df4e782012-06-21 16:28:18605def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52606 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18607 problems = []
608 for f in input_api.AffectedFiles():
609 if (not f.LocalPath().endswith(('.cc', '.mm'))):
610 continue
611
612 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04613 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18614 problems.append(' %s:%d' % (f.LocalPath(), line_num))
615
616 if not problems:
617 return []
618 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
619 '\n'.join(problems))]
620
621
danakj61c1aa22015-10-26 19:55:52622def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57623 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52624 errors = []
625 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
626 input_api.re.MULTILINE)
627 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
628 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
629 continue
630 for lnum, line in f.ChangedContents():
631 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17632 errors.append(output_api.PresubmitError(
633 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57634 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17635 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52636 return errors
637
638
mcasasb7440c282015-02-04 14:52:19639def _FindHistogramNameInLine(histogram_name, line):
640 """Tries to find a histogram name or prefix in a line."""
641 if not "affected-histogram" in line:
642 return histogram_name in line
643 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
644 # the histogram_name.
645 if not '"' in line:
646 return False
647 histogram_prefix = line.split('\"')[1]
648 return histogram_prefix in histogram_name
649
650
651def _CheckUmaHistogramChanges(input_api, output_api):
652 """Check that UMA histogram names in touched lines can still be found in other
653 lines of the patch or in histograms.xml. Note that this check would not catch
654 the reverse: changes in histograms.xml not matched in the code itself."""
655 touched_histograms = []
656 histograms_xml_modifications = []
657 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
658 for f in input_api.AffectedFiles():
659 # If histograms.xml itself is modified, keep the modified lines for later.
660 if f.LocalPath().endswith(('histograms.xml')):
661 histograms_xml_modifications = f.ChangedContents()
662 continue
663 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
664 continue
665 for line_num, line in f.ChangedContents():
666 found = pattern.search(line)
667 if found:
668 touched_histograms.append([found.group(1), f, line_num])
669
670 # Search for the touched histogram names in the local modifications to
671 # histograms.xml, and, if not found, on the base histograms.xml file.
672 unmatched_histograms = []
673 for histogram_info in touched_histograms:
674 histogram_name_found = False
675 for line_num, line in histograms_xml_modifications:
676 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
677 if histogram_name_found:
678 break
679 if not histogram_name_found:
680 unmatched_histograms.append(histogram_info)
681
eromanb90c82e7e32015-04-01 15:13:49682 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19683 problems = []
684 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49685 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19686 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45687 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19688 histogram_name_found = False
689 for line in histograms_xml:
690 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
691 if histogram_name_found:
692 break
693 if not histogram_name_found:
694 problems.append(' [%s:%d] %s' %
695 (f.LocalPath(), line_num, histogram_name))
696
697 if not problems:
698 return []
699 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
700 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49701 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19702
wnwenbdc444e2016-05-25 13:44:15703
yolandyandaabc6d2016-04-18 18:29:39704def _CheckFlakyTestUsage(input_api, output_api):
705 """Check that FlakyTest annotation is our own instead of the android one"""
706 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
707 files = []
708 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
709 if f.LocalPath().endswith('Test.java'):
710 if pattern.search(input_api.ReadFile(f)):
711 files.append(f)
712 if len(files):
713 return [output_api.PresubmitError(
714 'Use org.chromium.base.test.util.FlakyTest instead of '
715 'android.test.FlakyTest',
716 files)]
717 return []
mcasasb7440c282015-02-04 14:52:19718
wnwenbdc444e2016-05-25 13:44:15719
[email protected]8ea5d4b2011-09-13 21:49:22720def _CheckNoNewWStrings(input_api, output_api):
721 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27722 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22723 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20724 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57725 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34726 '/win/' in f.LocalPath() or
727 'chrome_elf' in f.LocalPath() or
728 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20729 continue
[email protected]8ea5d4b2011-09-13 21:49:22730
[email protected]a11dbe9b2012-08-07 01:32:58731 allowWString = False
[email protected]b5c24292011-11-28 14:38:20732 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58733 if 'presubmit: allow wstring' in line:
734 allowWString = True
735 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27736 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58737 allowWString = False
738 else:
739 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22740
[email protected]55463aa62011-10-12 00:48:27741 if not problems:
742 return []
743 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58744 ' If you are calling a cross-platform API that accepts a wstring, '
745 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27746 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22747
748
[email protected]2a8ac9c2011-10-19 17:20:44749def _CheckNoDEPSGIT(input_api, output_api):
750 """Make sure .DEPS.git is never modified manually."""
751 if any(f.LocalPath().endswith('.DEPS.git') for f in
752 input_api.AffectedFiles()):
753 return [output_api.PresubmitError(
754 'Never commit changes to .DEPS.git. This file is maintained by an\n'
755 'automated system based on what\'s in DEPS and your changes will be\n'
756 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34757 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:44758 'for more information')]
759 return []
760
761
tandriief664692014-09-23 14:51:47762def _CheckValidHostsInDEPS(input_api, output_api):
763 """Checks that DEPS file deps are from allowed_hosts."""
764 # Run only if DEPS file has been modified to annoy fewer bystanders.
765 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
766 return []
767 # Outsource work to gclient verify
768 try:
769 input_api.subprocess.check_output(['gclient', 'verify'])
770 return []
771 except input_api.subprocess.CalledProcessError, error:
772 return [output_api.PresubmitError(
773 'DEPS file must have only git dependencies.',
774 long_text=error.output)]
775
776
[email protected]127f18ec2012-06-16 05:05:59777def _CheckNoBannedFunctions(input_api, output_api):
778 """Make sure that banned functions are not used."""
779 warnings = []
780 errors = []
781
wnwenbdc444e2016-05-25 13:44:15782 def IsBlacklisted(affected_file, blacklist):
783 local_path = affected_file.LocalPath()
784 for item in blacklist:
785 if input_api.re.match(item, local_path):
786 return True
787 return False
788
789 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
790 matched = False
791 if func_name[0:1] == '/':
792 regex = func_name[1:]
793 if input_api.re.search(regex, line):
794 matched = True
795 elif func_name in line:
dchenge07de812016-06-20 19:27:17796 matched = True
wnwenbdc444e2016-05-25 13:44:15797 if matched:
dchenge07de812016-06-20 19:27:17798 problems = warnings
wnwenbdc444e2016-05-25 13:44:15799 if error:
dchenge07de812016-06-20 19:27:17800 problems = errors
wnwenbdc444e2016-05-25 13:44:15801 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
802 for message_line in message:
803 problems.append(' %s' % message_line)
804
Eric Stevensona9a980972017-09-23 00:04:41805 file_filter = lambda f: f.LocalPath().endswith(('.java'))
806 for f in input_api.AffectedFiles(file_filter=file_filter):
807 for line_num, line in f.ChangedContents():
808 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
809 CheckForMatch(f, line_num, line, func_name, message, error)
810
[email protected]127f18ec2012-06-16 05:05:59811 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
812 for f in input_api.AffectedFiles(file_filter=file_filter):
813 for line_num, line in f.ChangedContents():
814 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15815 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59816
817 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
818 for f in input_api.AffectedFiles(file_filter=file_filter):
819 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49820 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49821 if IsBlacklisted(f, excluded_paths):
822 continue
wnwenbdc444e2016-05-25 13:44:15823 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59824
825 result = []
826 if (warnings):
827 result.append(output_api.PresubmitPromptWarning(
828 'Banned functions were used.\n' + '\n'.join(warnings)))
829 if (errors):
830 result.append(output_api.PresubmitError(
831 'Banned functions were used.\n' + '\n'.join(errors)))
832 return result
833
834
[email protected]6c063c62012-07-11 19:11:06835def _CheckNoPragmaOnce(input_api, output_api):
836 """Make sure that banned functions are not used."""
837 files = []
838 pattern = input_api.re.compile(r'^#pragma\s+once',
839 input_api.re.MULTILINE)
840 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
841 if not f.LocalPath().endswith('.h'):
842 continue
843 contents = input_api.ReadFile(f)
844 if pattern.search(contents):
845 files.append(f)
846
847 if files:
848 return [output_api.PresubmitError(
849 'Do not use #pragma once in header files.\n'
850 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
851 files)]
852 return []
853
[email protected]127f18ec2012-06-16 05:05:59854
[email protected]e7479052012-09-19 00:26:12855def _CheckNoTrinaryTrueFalse(input_api, output_api):
856 """Checks to make sure we don't introduce use of foo ? true : false."""
857 problems = []
858 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
859 for f in input_api.AffectedFiles():
860 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
861 continue
862
863 for line_num, line in f.ChangedContents():
864 if pattern.match(line):
865 problems.append(' %s:%d' % (f.LocalPath(), line_num))
866
867 if not problems:
868 return []
869 return [output_api.PresubmitPromptWarning(
870 'Please consider avoiding the "? true : false" pattern if possible.\n' +
871 '\n'.join(problems))]
872
873
[email protected]55f9f382012-07-31 11:02:18874def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28875 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18876 change. Breaking - rules is an error, breaking ! rules is a
877 warning.
878 """
mohan.reddyf21db962014-10-16 12:26:47879 import sys
[email protected]55f9f382012-07-31 11:02:18880 # We need to wait until we have an input_api object and use this
881 # roundabout construct to import checkdeps because this file is
882 # eval-ed and thus doesn't have __file__.
883 original_sys_path = sys.path
884 try:
885 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47886 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18887 import checkdeps
888 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:24889 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:28890 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18891 from rules import Rule
892 finally:
893 # Restore sys.path to what it was before.
894 sys.path = original_sys_path
895
896 added_includes = []
rhalavati08acd232017-04-03 07:23:28897 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:24898 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:18899 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28900 if CppChecker.IsCppFile(f.LocalPath()):
901 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08902 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:28903 elif ProtoChecker.IsProtoFile(f.LocalPath()):
904 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08905 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:24906 elif JavaChecker.IsJavaFile(f.LocalPath()):
907 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08908 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18909
[email protected]26385172013-05-09 23:11:35910 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18911
912 error_descriptions = []
913 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28914 error_subjects = set()
915 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18916 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
917 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:08918 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18919 description_with_path = '%s\n %s' % (path, rule_description)
920 if rule_type == Rule.DISALLOW:
921 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28922 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18923 else:
924 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28925 warning_subjects.add("#includes")
926
927 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
928 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:08929 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:28930 description_with_path = '%s\n %s' % (path, rule_description)
931 if rule_type == Rule.DISALLOW:
932 error_descriptions.append(description_with_path)
933 error_subjects.add("imports")
934 else:
935 warning_descriptions.append(description_with_path)
936 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18937
Jinsuk Kim5a092672017-10-24 22:42:24938 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:02939 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:08940 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:24941 description_with_path = '%s\n %s' % (path, rule_description)
942 if rule_type == Rule.DISALLOW:
943 error_descriptions.append(description_with_path)
944 error_subjects.add("imports")
945 else:
946 warning_descriptions.append(description_with_path)
947 warning_subjects.add("imports")
948
[email protected]55f9f382012-07-31 11:02:18949 results = []
950 if error_descriptions:
951 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28952 'You added one or more %s that violate checkdeps rules.'
953 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18954 error_descriptions))
955 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42956 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28957 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18958 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28959 '%s? See relevant DEPS file(s) for details and contacts.' %
960 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18961 warning_descriptions))
962 return results
963
964
[email protected]fbcafe5a2012-08-08 15:31:22965def _CheckFilePermissions(input_api, output_api):
966 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15967 if input_api.platform == 'win32':
968 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29969 checkperms_tool = input_api.os_path.join(
970 input_api.PresubmitLocalPath(),
971 'tools', 'checkperms', 'checkperms.py')
972 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47973 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:39974 with input_api.CreateTemporaryFile() as file_list:
975 for f in input_api.AffectedFiles():
976 # checkperms.py file/directory arguments must be relative to the
977 # repository.
978 file_list.write(f.LocalPath() + '\n')
979 file_list.close()
980 args += ['--file-list', file_list.name]
981 try:
982 input_api.subprocess.check_output(args)
983 return []
984 except input_api.subprocess.CalledProcessError as error:
985 return [output_api.PresubmitError(
986 'checkperms.py failed:',
987 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22988
989
robertocn832f5992017-01-04 19:01:30990def _CheckTeamTags(input_api, output_api):
991 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
992 checkteamtags_tool = input_api.os_path.join(
993 input_api.PresubmitLocalPath(),
994 'tools', 'checkteamtags', 'checkteamtags.py')
995 args = [input_api.python_executable, checkteamtags_tool,
996 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22997 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30998 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
999 'OWNERS']
1000 try:
1001 if files:
1002 input_api.subprocess.check_output(args + files)
1003 return []
1004 except input_api.subprocess.CalledProcessError as error:
1005 return [output_api.PresubmitError(
1006 'checkteamtags.py failed:',
1007 long_text=error.output)]
1008
1009
[email protected]c8278b32012-10-30 20:35:491010def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
1011 """Makes sure we don't include ui/aura/window_property.h
1012 in header files.
1013 """
1014 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1015 errors = []
1016 for f in input_api.AffectedFiles():
1017 if not f.LocalPath().endswith('.h'):
1018 continue
1019 for line_num, line in f.ChangedContents():
1020 if pattern.match(line):
1021 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1022
1023 results = []
1024 if errors:
1025 results.append(output_api.PresubmitError(
1026 'Header files should not include ui/aura/window_property.h', errors))
1027 return results
1028
1029
[email protected]70ca77752012-11-20 03:45:031030def _CheckForVersionControlConflictsInFile(input_api, f):
1031 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1032 errors = []
1033 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231034 if f.LocalPath().endswith('.md'):
1035 # First-level headers in markdown look a lot like version control
1036 # conflict markers. http://daringfireball.net/projects/markdown/basics
1037 continue
[email protected]70ca77752012-11-20 03:45:031038 if pattern.match(line):
1039 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1040 return errors
1041
1042
1043def _CheckForVersionControlConflicts(input_api, output_api):
1044 """Usually this is not intentional and will cause a compile failure."""
1045 errors = []
1046 for f in input_api.AffectedFiles():
1047 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1048
1049 results = []
1050 if errors:
1051 results.append(output_api.PresubmitError(
1052 'Version control conflict markers found, please resolve.', errors))
1053 return results
1054
estadee17314a02017-01-12 16:22:161055def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1056 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1057 errors = []
1058 for f in input_api.AffectedFiles():
1059 for line_num, line in f.ChangedContents():
1060 if pattern.search(line):
1061 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1062
1063 results = []
1064 if errors:
1065 results.append(output_api.PresubmitPromptWarning(
1066 'Found Google support URL addressed by answer number. Please replace with '
1067 'a p= identifier instead. See crbug.com/679462\n', errors))
1068 return results
1069
[email protected]70ca77752012-11-20 03:45:031070
[email protected]06e6d0ff2012-12-11 01:36:441071def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1072 def FilterFile(affected_file):
1073 """Filter function for use with input_api.AffectedSourceFiles,
1074 below. This filters out everything except non-test files from
1075 top-level directories that generally speaking should not hard-code
1076 service URLs (e.g. src/android_webview/, src/content/ and others).
1077 """
1078 return input_api.FilterSourceFile(
1079 affected_file,
[email protected]78bb39d62012-12-11 15:11:561080 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441081 black_list=(_EXCLUDED_PATHS +
1082 _TEST_CODE_EXCLUDED_PATHS +
1083 input_api.DEFAULT_BLACK_LIST))
1084
reillyi38965732015-11-16 18:27:331085 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1086 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461087 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1088 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441089 problems = [] # items are (filename, line_number, line)
1090 for f in input_api.AffectedSourceFiles(FilterFile):
1091 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461092 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441093 problems.append((f.LocalPath(), line_num, line))
1094
1095 if problems:
[email protected]f7051d52013-04-02 18:31:421096 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441097 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581098 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441099 [' %s:%d: %s' % (
1100 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031101 else:
1102 return []
[email protected]06e6d0ff2012-12-11 01:36:441103
1104
[email protected]d2530012013-01-25 16:39:271105def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1106 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311107 The native_client_sdk directory is excluded because it has auto-generated PNG
1108 files for documentation.
[email protected]d2530012013-01-25 16:39:271109 """
[email protected]d2530012013-01-25 16:39:271110 errors = []
binji0dcdf342014-12-12 18:32:311111 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1112 black_list = (r'^native_client_sdk[\\\/]',)
1113 file_filter = lambda f: input_api.FilterSourceFile(
1114 f, white_list=white_list, black_list=black_list)
1115 for f in input_api.AffectedFiles(include_deletes=False,
1116 file_filter=file_filter):
1117 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271118
1119 results = []
1120 if errors:
1121 results.append(output_api.PresubmitError(
1122 'The name of PNG files should not have abbreviations. \n'
1123 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1124 'Contact [email protected] if you have questions.', errors))
1125 return results
1126
1127
Daniel Cheng4dcdb6b2017-04-13 08:30:171128def _ExtractAddRulesFromParsedDeps(parsed_deps):
1129 """Extract the rules that add dependencies from a parsed DEPS file.
1130
1131 Args:
1132 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1133 add_rules = set()
1134 add_rules.update([
1135 rule[1:] for rule in parsed_deps.get('include_rules', [])
1136 if rule.startswith('+') or rule.startswith('!')
1137 ])
1138 for specific_file, rules in parsed_deps.get('specific_include_rules',
1139 {}).iteritems():
1140 add_rules.update([
1141 rule[1:] for rule in rules
1142 if rule.startswith('+') or rule.startswith('!')
1143 ])
1144 return add_rules
1145
1146
1147def _ParseDeps(contents):
1148 """Simple helper for parsing DEPS files."""
1149 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171150 class _VarImpl:
1151
1152 def __init__(self, local_scope):
1153 self._local_scope = local_scope
1154
1155 def Lookup(self, var_name):
1156 """Implements the Var syntax."""
1157 try:
1158 return self._local_scope['vars'][var_name]
1159 except KeyError:
1160 raise Exception('Var is not defined: %s' % var_name)
1161
1162 local_scope = {}
1163 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171164 'Var': _VarImpl(local_scope).Lookup,
1165 }
1166 exec contents in global_scope, local_scope
1167 return local_scope
1168
1169
1170def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081171 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411172 a set of DEPS entries that we should look up.
1173
1174 For a directory (rather than a specific filename) we fake a path to
1175 a specific filename by adding /DEPS. This is chosen as a file that
1176 will seldom or never be subject to per-file include_rules.
1177 """
[email protected]2b438d62013-11-14 17:54:141178 # We ignore deps entries on auto-generated directories.
1179 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081180
Daniel Cheng4dcdb6b2017-04-13 08:30:171181 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1182 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1183
1184 added_deps = new_deps.difference(old_deps)
1185
[email protected]2b438d62013-11-14 17:54:141186 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171187 for added_dep in added_deps:
1188 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1189 continue
1190 # Assume that a rule that ends in .h is a rule for a specific file.
1191 if added_dep.endswith('.h'):
1192 results.add(added_dep)
1193 else:
1194 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081195 return results
1196
1197
[email protected]e871964c2013-05-13 14:14:551198def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1199 """When a dependency prefixed with + is added to a DEPS file, we
1200 want to make sure that the change is reviewed by an OWNER of the
1201 target file or directory, to avoid layering violations from being
1202 introduced. This check verifies that this happens.
1203 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171204 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241205
1206 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191207 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241208 for f in input_api.AffectedFiles(include_deletes=False,
1209 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551210 filename = input_api.os_path.basename(f.LocalPath())
1211 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171212 virtual_depended_on_files.update(_CalculateAddedDeps(
1213 input_api.os_path,
1214 '\n'.join(f.OldContents()),
1215 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551216
[email protected]e871964c2013-05-13 14:14:551217 if not virtual_depended_on_files:
1218 return []
1219
1220 if input_api.is_committing:
1221 if input_api.tbr:
1222 return [output_api.PresubmitNotifyResult(
1223 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271224 if input_api.dry_run:
1225 return [output_api.PresubmitNotifyResult(
1226 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551227 if not input_api.change.issue:
1228 return [output_api.PresubmitError(
1229 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401230 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551231 output = output_api.PresubmitError
1232 else:
1233 output = output_api.PresubmitNotifyResult
1234
1235 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501236 owner_email, reviewers = (
1237 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1238 input_api,
1239 owners_db.email_regexp,
1240 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551241
1242 owner_email = owner_email or input_api.change.author_email
1243
[email protected]de4f7d22013-05-23 14:27:461244 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511245 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461246 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551247 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1248 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411249
1250 # We strip the /DEPS part that was added by
1251 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1252 # directory.
1253 def StripDeps(path):
1254 start_deps = path.rfind('/DEPS')
1255 if start_deps != -1:
1256 return path[:start_deps]
1257 else:
1258 return path
1259 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551260 for path in missing_files]
1261
1262 if unapproved_dependencies:
1263 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151264 output('You need LGTM from owners of depends-on paths in DEPS that were '
1265 'modified in this CL:\n %s' %
1266 '\n '.join(sorted(unapproved_dependencies)))]
1267 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1268 output_list.append(output(
1269 'Suggested missing target path OWNERS:\n %s' %
1270 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551271 return output_list
1272
1273 return []
1274
1275
[email protected]85218562013-11-22 07:41:401276def _CheckSpamLogging(input_api, output_api):
1277 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1278 black_list = (_EXCLUDED_PATHS +
1279 _TEST_CODE_EXCLUDED_PATHS +
1280 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501281 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191282 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481283 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461284 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121285 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1286 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581287 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591288 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161289 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031290 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151291 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1292 r"^chromecast[\\\/]",
1293 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481294 r"^components[\\\/]browser_watcher[\\\/]"
1295 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311296 r"^components[\\\/]html_viewer[\\\/]"
1297 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461298 # TODO(peter): Remove this exception. https://crbug.com/534537
1299 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1300 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251301 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1302 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241303 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111304 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151305 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111306 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521307 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501308 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361309 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311310 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131311 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001312 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441313 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451314 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021315 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351316 r"dump_file_system.cc$",
1317 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401318 source_file_filter = lambda x: input_api.FilterSourceFile(
1319 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1320
thomasanderson625d3932017-03-29 07:16:581321 log_info = set([])
1322 printf = set([])
[email protected]85218562013-11-22 07:41:401323
1324 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581325 for _, line in f.ChangedContents():
1326 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1327 log_info.add(f.LocalPath())
1328 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1329 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371330
thomasanderson625d3932017-03-29 07:16:581331 if input_api.re.search(r"\bprintf\(", line):
1332 printf.add(f.LocalPath())
1333 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1334 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401335
1336 if log_info:
1337 return [output_api.PresubmitError(
1338 'These files spam the console log with LOG(INFO):',
1339 items=log_info)]
1340 if printf:
1341 return [output_api.PresubmitError(
1342 'These files spam the console log with printf/fprintf:',
1343 items=printf)]
1344 return []
1345
1346
[email protected]49aa76a2013-12-04 06:59:161347def _CheckForAnonymousVariables(input_api, output_api):
1348 """These types are all expected to hold locks while in scope and
1349 so should never be anonymous (which causes them to be immediately
1350 destroyed)."""
1351 they_who_must_be_named = [
1352 'base::AutoLock',
1353 'base::AutoReset',
1354 'base::AutoUnlock',
1355 'SkAutoAlphaRestore',
1356 'SkAutoBitmapShaderInstall',
1357 'SkAutoBlitterChoose',
1358 'SkAutoBounderCommit',
1359 'SkAutoCallProc',
1360 'SkAutoCanvasRestore',
1361 'SkAutoCommentBlock',
1362 'SkAutoDescriptor',
1363 'SkAutoDisableDirectionCheck',
1364 'SkAutoDisableOvalCheck',
1365 'SkAutoFree',
1366 'SkAutoGlyphCache',
1367 'SkAutoHDC',
1368 'SkAutoLockColors',
1369 'SkAutoLockPixels',
1370 'SkAutoMalloc',
1371 'SkAutoMaskFreeImage',
1372 'SkAutoMutexAcquire',
1373 'SkAutoPathBoundsUpdate',
1374 'SkAutoPDFRelease',
1375 'SkAutoRasterClipValidate',
1376 'SkAutoRef',
1377 'SkAutoTime',
1378 'SkAutoTrace',
1379 'SkAutoUnref',
1380 ]
1381 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1382 # bad: base::AutoLock(lock.get());
1383 # not bad: base::AutoLock lock(lock.get());
1384 bad_pattern = input_api.re.compile(anonymous)
1385 # good: new base::AutoLock(lock.get())
1386 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1387 errors = []
1388
1389 for f in input_api.AffectedFiles():
1390 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1391 continue
1392 for linenum, line in f.ChangedContents():
1393 if bad_pattern.search(line) and not good_pattern.search(line):
1394 errors.append('%s:%d' % (f.LocalPath(), linenum))
1395
1396 if errors:
1397 return [output_api.PresubmitError(
1398 'These lines create anonymous variables that need to be named:',
1399 items=errors)]
1400 return []
1401
1402
Peter Kasting4844e46e2018-02-23 07:27:101403def _CheckUniquePtr(input_api, output_api):
1404 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1405 sources = lambda affected_file: input_api.FilterSourceFile(
1406 affected_file,
1407 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1408 input_api.DEFAULT_BLACK_LIST),
1409 white_list=(file_inclusion_pattern,))
1410 return_construct_pattern = input_api.re.compile(
1411 r'(=|\breturn)\s*std::unique_ptr<.*?(?<!])>\([^)]+\)')
1412 null_construct_pattern = input_api.re.compile(
1413 r'\b(?<!<)std::unique_ptr<.*?>\(\)')
1414 errors = []
1415 for f in input_api.AffectedSourceFiles(sources):
1416 for line_number, line in f.ChangedContents():
1417 # Disallow:
1418 # return std::unique_ptr<T>(foo);
1419 # bar = std::unique_ptr<T>(foo);
1420 # But allow:
1421 # return std::unique_ptr<T[]>(foo);
1422 # bar = std::unique_ptr<T[]>(foo);
1423 if return_construct_pattern.search(line):
1424 errors.append(output_api.PresubmitError(
1425 ('%s:%d uses explicit std::unique_ptr constructor. ' +
1426 'Use std::make_unique<T>() instead.') %
1427 (f.LocalPath(), line_number)))
1428 # Disallow:
1429 # std::unique_ptr<T>()
1430 if null_construct_pattern.search(line):
1431 errors.append(output_api.PresubmitError(
1432 '%s:%d uses std::unique_ptr<T>(). Use nullptr instead.' %
1433 (f.LocalPath(), line_number)))
1434 return errors
1435
1436
[email protected]999261d2014-03-03 20:08:081437def _CheckUserActionUpdate(input_api, output_api):
1438 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521439 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081440 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521441 # If actions.xml is already included in the changelist, the PRESUBMIT
1442 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081443 return []
1444
[email protected]999261d2014-03-03 20:08:081445 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1446 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521447 current_actions = None
[email protected]999261d2014-03-03 20:08:081448 for f in input_api.AffectedFiles(file_filter=file_filter):
1449 for line_num, line in f.ChangedContents():
1450 match = input_api.re.search(action_re, line)
1451 if match:
[email protected]2f92dec2014-03-07 19:21:521452 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1453 # loaded only once.
1454 if not current_actions:
1455 with open('tools/metrics/actions/actions.xml') as actions_f:
1456 current_actions = actions_f.read()
1457 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081458 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521459 action = 'name="{0}"'.format(action_name)
1460 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081461 return [output_api.PresubmitPromptWarning(
1462 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521463 'tools/metrics/actions/actions.xml. Please run '
1464 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081465 % (f.LocalPath(), line_num, action_name))]
1466 return []
1467
1468
Daniel Cheng13ca61a882017-08-25 15:11:251469def _ImportJSONCommentEater(input_api):
1470 import sys
1471 sys.path = sys.path + [input_api.os_path.join(
1472 input_api.PresubmitLocalPath(),
1473 'tools', 'json_comment_eater')]
1474 import json_comment_eater
1475 return json_comment_eater
1476
1477
[email protected]99171a92014-06-03 08:44:471478def _GetJSONParseError(input_api, filename, eat_comments=True):
1479 try:
1480 contents = input_api.ReadFile(filename)
1481 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251482 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131483 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471484
1485 input_api.json.loads(contents)
1486 except ValueError as e:
1487 return e
1488 return None
1489
1490
1491def _GetIDLParseError(input_api, filename):
1492 try:
1493 contents = input_api.ReadFile(filename)
1494 idl_schema = input_api.os_path.join(
1495 input_api.PresubmitLocalPath(),
1496 'tools', 'json_schema_compiler', 'idl_schema.py')
1497 process = input_api.subprocess.Popen(
1498 [input_api.python_executable, idl_schema],
1499 stdin=input_api.subprocess.PIPE,
1500 stdout=input_api.subprocess.PIPE,
1501 stderr=input_api.subprocess.PIPE,
1502 universal_newlines=True)
1503 (_, error) = process.communicate(input=contents)
1504 return error or None
1505 except ValueError as e:
1506 return e
1507
1508
1509def _CheckParseErrors(input_api, output_api):
1510 """Check that IDL and JSON files do not contain syntax errors."""
1511 actions = {
1512 '.idl': _GetIDLParseError,
1513 '.json': _GetJSONParseError,
1514 }
[email protected]99171a92014-06-03 08:44:471515 # Most JSON files are preprocessed and support comments, but these do not.
1516 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491517 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471518 ]
1519 # Only run IDL checker on files in these directories.
1520 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491521 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1522 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471523 ]
1524
1525 def get_action(affected_file):
1526 filename = affected_file.LocalPath()
1527 return actions.get(input_api.os_path.splitext(filename)[1])
1528
[email protected]99171a92014-06-03 08:44:471529 def FilterFile(affected_file):
1530 action = get_action(affected_file)
1531 if not action:
1532 return False
1533 path = affected_file.LocalPath()
1534
Sean Kau46e29bc2017-08-28 16:31:161535 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471536 return False
1537
1538 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161539 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471540 return False
1541 return True
1542
1543 results = []
1544 for affected_file in input_api.AffectedFiles(
1545 file_filter=FilterFile, include_deletes=False):
1546 action = get_action(affected_file)
1547 kwargs = {}
1548 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161549 _MatchesFile(input_api, json_no_comments_patterns,
1550 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471551 kwargs['eat_comments'] = False
1552 parse_error = action(input_api,
1553 affected_file.AbsoluteLocalPath(),
1554 **kwargs)
1555 if parse_error:
1556 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1557 (affected_file.LocalPath(), parse_error)))
1558 return results
1559
1560
[email protected]760deea2013-12-10 19:33:491561def _CheckJavaStyle(input_api, output_api):
1562 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471563 import sys
[email protected]760deea2013-12-10 19:33:491564 original_sys_path = sys.path
1565 try:
1566 sys.path = sys.path + [input_api.os_path.join(
1567 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1568 import checkstyle
1569 finally:
1570 # Restore sys.path to what it was before.
1571 sys.path = original_sys_path
1572
1573 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091574 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511575 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491576
1577
Sean Kau46e29bc2017-08-28 16:31:161578def _MatchesFile(input_api, patterns, path):
1579 for pattern in patterns:
1580 if input_api.re.search(pattern, path):
1581 return True
1582 return False
1583
1584
Daniel Cheng7052cdf2017-11-21 19:23:291585def _GetOwnersFilesToCheckForIpcOwners(input_api):
1586 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:171587
Daniel Cheng7052cdf2017-11-21 19:23:291588 Returns:
1589 A dictionary mapping an OWNER file to the list of OWNERS rules it must
1590 contain to cover IPC-related files with noparent reviewer rules.
1591 """
1592 # Whether or not a file affects IPC is (mostly) determined by a simple list
1593 # of filename patterns.
dchenge07de812016-06-20 19:27:171594 file_patterns = [
palmerb19a0932017-01-24 04:00:311595 # Legacy IPC:
dchenge07de812016-06-20 19:27:171596 '*_messages.cc',
1597 '*_messages*.h',
1598 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311599 # Mojo IPC:
dchenge07de812016-06-20 19:27:171600 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:471601 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:171602 '*_struct_traits*.*',
1603 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311604 '*.typemap',
1605 # Android native IPC:
1606 '*.aidl',
1607 # Blink uses a different file naming convention:
1608 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:471609 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:171610 '*StructTraits*.*',
1611 '*TypeConverter*.*',
1612 ]
1613
scottmg7a6ed5ba2016-11-04 18:22:041614 # These third_party directories do not contain IPCs, but contain files
1615 # matching the above patterns, which trigger false positives.
1616 exclude_paths = [
1617 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291618 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041619 ]
1620
dchenge07de812016-06-20 19:27:171621 # Dictionary mapping an OWNERS file path to Patterns.
1622 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1623 # rules ) to a PatternEntry.
1624 # PatternEntry is a dictionary with two keys:
1625 # - 'files': the files that are matched by this pattern
1626 # - 'rules': the per-file rules needed for this pattern
1627 # For example, if we expect OWNERS file to contain rules for *.mojom and
1628 # *_struct_traits*.*, Patterns might look like this:
1629 # {
1630 # '*.mojom': {
1631 # 'files': ...,
1632 # 'rules': [
1633 # 'per-file *.mojom=set noparent',
1634 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1635 # ],
1636 # },
1637 # '*_struct_traits*.*': {
1638 # 'files': ...,
1639 # 'rules': [
1640 # 'per-file *_struct_traits*.*=set noparent',
1641 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1642 # ],
1643 # },
1644 # }
1645 to_check = {}
1646
Daniel Cheng13ca61a882017-08-25 15:11:251647 def AddPatternToCheck(input_file, pattern):
1648 owners_file = input_api.os_path.join(
1649 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1650 if owners_file not in to_check:
1651 to_check[owners_file] = {}
1652 if pattern not in to_check[owners_file]:
1653 to_check[owners_file][pattern] = {
1654 'files': [],
1655 'rules': [
1656 'per-file %s=set noparent' % pattern,
1657 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1658 ]
1659 }
1660 to_check[owners_file][pattern]['files'].append(f)
1661
dchenge07de812016-06-20 19:27:171662 # Iterate through the affected files to see what we actually need to check
1663 # for. We should only nag patch authors about per-file rules if a file in that
1664 # directory would match that pattern. If a directory only contains *.mojom
1665 # files and no *_messages*.h files, we should only nag about rules for
1666 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251667 for f in input_api.AffectedFiles(include_deletes=False):
1668 # Manifest files don't have a strong naming convention. Instead, scan
1669 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161670 if (f.LocalPath().endswith('.json') and
1671 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1672 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251673 json_comment_eater = _ImportJSONCommentEater(input_api)
1674 mostly_json_lines = '\n'.join(f.NewContents())
1675 # Comments aren't allowed in strict JSON, so filter them out.
1676 json_lines = json_comment_eater.Nom(mostly_json_lines)
1677 json_content = input_api.json.loads(json_lines)
1678 if 'interface_provider_specs' in json_content:
1679 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171680 for pattern in file_patterns:
1681 if input_api.fnmatch.fnmatch(
1682 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041683 skip = False
1684 for exclude in exclude_paths:
1685 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1686 skip = True
1687 break
1688 if skip:
1689 continue
Daniel Cheng13ca61a882017-08-25 15:11:251690 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171691 break
1692
Daniel Cheng7052cdf2017-11-21 19:23:291693 return to_check
1694
1695
1696def _CheckIpcOwners(input_api, output_api):
1697 """Checks that affected files involving IPC have an IPC OWNERS rule."""
1698 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
1699
1700 if to_check:
1701 # If there are any OWNERS files to check, there are IPC-related changes in
1702 # this CL. Auto-CC the review list.
1703 output_api.AppendCC('[email protected]')
1704
1705 # Go through the OWNERS files to check, filtering out rules that are already
1706 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:171707 for owners_file, patterns in to_check.iteritems():
1708 try:
1709 with file(owners_file) as f:
1710 lines = set(f.read().splitlines())
1711 for entry in patterns.itervalues():
1712 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1713 ]
1714 except IOError:
1715 # No OWNERS file, so all the rules are definitely missing.
1716 continue
1717
1718 # All the remaining lines weren't found in OWNERS files, so emit an error.
1719 errors = []
1720 for owners_file, patterns in to_check.iteritems():
1721 missing_lines = []
1722 files = []
1723 for pattern, entry in patterns.iteritems():
1724 missing_lines.extend(entry['rules'])
1725 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1726 if missing_lines:
1727 errors.append(
Daniel Cheng52111692017-06-14 08:00:591728 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171729 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1730
1731 results = []
1732 if errors:
vabrf5ce3bf92016-07-11 14:52:411733 if input_api.is_committing:
1734 output = output_api.PresubmitError
1735 else:
1736 output = output_api.PresubmitPromptWarning
1737 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591738 'Found OWNERS files that need to be updated for IPC security ' +
1739 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171740 long_text='\n\n'.join(errors)))
1741
1742 return results
1743
1744
jbriance9e12f162016-11-25 07:57:501745def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311746 """Checks that added or removed lines in non third party affected
1747 header files do not lead to new useless class or struct forward
1748 declaration.
jbriance9e12f162016-11-25 07:57:501749 """
1750 results = []
1751 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1752 input_api.re.MULTILINE)
1753 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1754 input_api.re.MULTILINE)
1755 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311756 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191757 not f.LocalPath().startswith('third_party/blink') and
1758 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311759 not f.LocalPath().startswith('third_party/WebKit') and
1760 not f.LocalPath().startswith('third_party\\WebKit')):
1761 continue
1762
jbriance9e12f162016-11-25 07:57:501763 if not f.LocalPath().endswith('.h'):
1764 continue
1765
1766 contents = input_api.ReadFile(f)
1767 fwd_decls = input_api.re.findall(class_pattern, contents)
1768 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1769
1770 useless_fwd_decls = []
1771 for decl in fwd_decls:
1772 count = sum(1 for _ in input_api.re.finditer(
1773 r'\b%s\b' % input_api.re.escape(decl), contents))
1774 if count == 1:
1775 useless_fwd_decls.append(decl)
1776
1777 if not useless_fwd_decls:
1778 continue
1779
1780 for line in f.GenerateScmDiff().splitlines():
1781 if (line.startswith('-') and not line.startswith('--') or
1782 line.startswith('+') and not line.startswith('++')):
1783 for decl in useless_fwd_decls:
1784 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1785 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241786 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501787 (f.LocalPath(), decl)))
1788 useless_fwd_decls.remove(decl)
1789
1790 return results
1791
1792
dskiba88634f4e2015-08-14 23:03:291793def _CheckAndroidToastUsage(input_api, output_api):
1794 """Checks that code uses org.chromium.ui.widget.Toast instead of
1795 android.widget.Toast (Chromium Toast doesn't force hardware
1796 acceleration on low-end devices, saving memory).
1797 """
1798 toast_import_pattern = input_api.re.compile(
1799 r'^import android\.widget\.Toast;$')
1800
1801 errors = []
1802
1803 sources = lambda affected_file: input_api.FilterSourceFile(
1804 affected_file,
1805 black_list=(_EXCLUDED_PATHS +
1806 _TEST_CODE_EXCLUDED_PATHS +
1807 input_api.DEFAULT_BLACK_LIST +
1808 (r'^chromecast[\\\/].*',
1809 r'^remoting[\\\/].*')),
1810 white_list=(r'.*\.java$',))
1811
1812 for f in input_api.AffectedSourceFiles(sources):
1813 for line_num, line in f.ChangedContents():
1814 if toast_import_pattern.search(line):
1815 errors.append("%s:%d" % (f.LocalPath(), line_num))
1816
1817 results = []
1818
1819 if errors:
1820 results.append(output_api.PresubmitError(
1821 'android.widget.Toast usage is detected. Android toasts use hardware'
1822 ' acceleration, and can be\ncostly on low-end devices. Please use'
1823 ' org.chromium.ui.widget.Toast instead.\n'
1824 'Contact [email protected] if you have any questions.',
1825 errors))
1826
1827 return results
1828
1829
dgnaa68d5e2015-06-10 10:08:221830def _CheckAndroidCrLogUsage(input_api, output_api):
1831 """Checks that new logs using org.chromium.base.Log:
1832 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511833 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221834 """
pkotwicza1dd0b002016-05-16 14:41:041835
torne89540622017-03-24 19:41:301836 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041837 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301838 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041839 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301840 # WebView license viewer code cannot depend on //base; used in stub APK.
1841 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1842 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041843 ]
1844
dgnaa68d5e2015-06-10 10:08:221845 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121846 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1847 class_in_base_pattern = input_api.re.compile(
1848 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1849 has_some_log_import_pattern = input_api.re.compile(
1850 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221851 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121852 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221853 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511854 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221855 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221856
Vincent Scheib16d7b272015-09-15 18:09:071857 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221858 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041859 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1860 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121861
dgnaa68d5e2015-06-10 10:08:221862 tag_decl_errors = []
1863 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121864 tag_errors = []
dgn38736db2015-09-18 19:20:511865 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121866 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221867
1868 for f in input_api.AffectedSourceFiles(sources):
1869 file_content = input_api.ReadFile(f)
1870 has_modified_logs = False
1871
1872 # Per line checks
dgn87d9fb62015-06-12 09:15:121873 if (cr_log_import_pattern.search(file_content) or
1874 (class_in_base_pattern.search(file_content) and
1875 not has_some_log_import_pattern.search(file_content))):
1876 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221877 for line_num, line in f.ChangedContents():
1878
1879 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121880 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221881 if match:
1882 has_modified_logs = True
1883
1884 # Make sure it uses "TAG"
1885 if not match.group('tag') == 'TAG':
1886 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121887 else:
1888 # Report non cr Log function calls in changed lines
1889 for line_num, line in f.ChangedContents():
1890 if log_call_pattern.search(line):
1891 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221892
1893 # Per file checks
1894 if has_modified_logs:
1895 # Make sure the tag is using the "cr" prefix and is not too long
1896 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511897 tag_name = match.group('name') if match else None
1898 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221899 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511900 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221901 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511902 elif '.' in tag_name:
1903 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221904
1905 results = []
1906 if tag_decl_errors:
1907 results.append(output_api.PresubmitPromptWarning(
1908 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511909 '"private static final String TAG = "<package tag>".\n'
1910 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221911 tag_decl_errors))
1912
1913 if tag_length_errors:
1914 results.append(output_api.PresubmitError(
1915 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511916 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221917 tag_length_errors))
1918
1919 if tag_errors:
1920 results.append(output_api.PresubmitPromptWarning(
1921 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1922 tag_errors))
1923
dgn87d9fb62015-06-12 09:15:121924 if util_log_errors:
dgn4401aa52015-04-29 16:26:171925 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121926 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1927 util_log_errors))
1928
dgn38736db2015-09-18 19:20:511929 if tag_with_dot_errors:
1930 results.append(output_api.PresubmitPromptWarning(
1931 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1932 tag_with_dot_errors))
1933
dgn4401aa52015-04-29 16:26:171934 return results
1935
1936
Yoland Yanb92fa522017-08-28 17:37:061937def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1938 """Checks that junit.framework.* is no longer used."""
1939 deprecated_junit_framework_pattern = input_api.re.compile(
1940 r'^import junit\.framework\..*;',
1941 input_api.re.MULTILINE)
1942 sources = lambda x: input_api.FilterSourceFile(
1943 x, white_list=(r'.*\.java$',), black_list=None)
1944 errors = []
1945 for f in input_api.AffectedFiles(sources):
1946 for line_num, line in f.ChangedContents():
1947 if deprecated_junit_framework_pattern.search(line):
1948 errors.append("%s:%d" % (f.LocalPath(), line_num))
1949
1950 results = []
1951 if errors:
1952 results.append(output_api.PresubmitError(
1953 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1954 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1955 ' if you have any question.', errors))
1956 return results
1957
1958
1959def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1960 """Checks that if new Java test classes have inheritance.
1961 Either the new test class is JUnit3 test or it is a JUnit4 test class
1962 with a base class, either case is undesirable.
1963 """
1964 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1965
1966 sources = lambda x: input_api.FilterSourceFile(
1967 x, white_list=(r'.*Test\.java$',), black_list=None)
1968 errors = []
1969 for f in input_api.AffectedFiles(sources):
1970 if not f.OldContents():
1971 class_declaration_start_flag = False
1972 for line_num, line in f.ChangedContents():
1973 if class_declaration_pattern.search(line):
1974 class_declaration_start_flag = True
1975 if class_declaration_start_flag and ' extends ' in line:
1976 errors.append('%s:%d' % (f.LocalPath(), line_num))
1977 if '{' in line:
1978 class_declaration_start_flag = False
1979
1980 results = []
1981 if errors:
1982 results.append(output_api.PresubmitPromptWarning(
1983 'The newly created files include Test classes that inherits from base'
1984 ' class. Please do not use inheritance in JUnit4 tests or add new'
1985 ' JUnit3 tests. Contact [email protected] if you have any'
1986 ' questions.', errors))
1987 return results
1988
yolandyan45001472016-12-21 21:12:421989def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1990 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1991 deprecated_annotation_import_pattern = input_api.re.compile(
1992 r'^import android\.test\.suitebuilder\.annotation\..*;',
1993 input_api.re.MULTILINE)
1994 sources = lambda x: input_api.FilterSourceFile(
1995 x, white_list=(r'.*\.java$',), black_list=None)
1996 errors = []
1997 for f in input_api.AffectedFiles(sources):
1998 for line_num, line in f.ChangedContents():
1999 if deprecated_annotation_import_pattern.search(line):
2000 errors.append("%s:%d" % (f.LocalPath(), line_num))
2001
2002 results = []
2003 if errors:
2004 results.append(output_api.PresubmitError(
2005 'Annotations in android.test.suitebuilder.annotation have been'
2006 ' deprecated since API level 24. Please use android.support.test.filters'
2007 ' from //third_party/android_support_test_runner:runner_java instead.'
2008 ' Contact [email protected] if you have any questions.', errors))
2009 return results
2010
2011
agrieve7b6479d82015-10-07 14:24:222012def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
2013 """Checks if MDPI assets are placed in a correct directory."""
2014 file_filter = lambda f: (f.LocalPath().endswith('.png') and
2015 ('/res/drawable/' in f.LocalPath() or
2016 '/res/drawable-ldrtl/' in f.LocalPath()))
2017 errors = []
2018 for f in input_api.AffectedFiles(include_deletes=False,
2019 file_filter=file_filter):
2020 errors.append(' %s' % f.LocalPath())
2021
2022 results = []
2023 if errors:
2024 results.append(output_api.PresubmitError(
2025 'MDPI assets should be placed in /res/drawable-mdpi/ or '
2026 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
2027 '/res/drawable-ldrtl/.\n'
2028 'Contact [email protected] if you have questions.', errors))
2029 return results
2030
2031
Nate Fischer535972b2017-09-16 01:06:182032def _CheckAndroidWebkitImports(input_api, output_api):
2033 """Checks that code uses org.chromium.base.Callback instead of
2034 android.widget.ValueCallback except in the WebView glue layer.
2035 """
2036 valuecallback_import_pattern = input_api.re.compile(
2037 r'^import android\.webkit\.ValueCallback;$')
2038
2039 errors = []
2040
2041 sources = lambda affected_file: input_api.FilterSourceFile(
2042 affected_file,
2043 black_list=(_EXCLUDED_PATHS +
2044 _TEST_CODE_EXCLUDED_PATHS +
2045 input_api.DEFAULT_BLACK_LIST +
2046 (r'^android_webview[\\\/]glue[\\\/].*',)),
2047 white_list=(r'.*\.java$',))
2048
2049 for f in input_api.AffectedSourceFiles(sources):
2050 for line_num, line in f.ChangedContents():
2051 if valuecallback_import_pattern.search(line):
2052 errors.append("%s:%d" % (f.LocalPath(), line_num))
2053
2054 results = []
2055
2056 if errors:
2057 results.append(output_api.PresubmitError(
2058 'android.webkit.ValueCallback usage is detected outside of the glue'
2059 ' layer. To stay compatible with the support library, android.webkit.*'
2060 ' classes should only be used inside the glue layer and'
2061 ' org.chromium.base.Callback should be used instead.',
2062 errors))
2063
2064 return results
2065
2066
agrievef32bcc72016-04-04 14:57:402067class PydepsChecker(object):
2068 def __init__(self, input_api, pydeps_files):
2069 self._file_cache = {}
2070 self._input_api = input_api
2071 self._pydeps_files = pydeps_files
2072
2073 def _LoadFile(self, path):
2074 """Returns the list of paths within a .pydeps file relative to //."""
2075 if path not in self._file_cache:
2076 with open(path) as f:
2077 self._file_cache[path] = f.read()
2078 return self._file_cache[path]
2079
2080 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
2081 """Returns an interable of paths within the .pydep, relativized to //."""
2082 os_path = self._input_api.os_path
2083 pydeps_dir = os_path.dirname(pydeps_path)
2084 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2085 if not l.startswith('*'))
2086 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2087
2088 def _CreateFilesToPydepsMap(self):
2089 """Returns a map of local_path -> list_of_pydeps."""
2090 ret = {}
2091 for pydep_local_path in self._pydeps_files:
2092 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2093 ret.setdefault(path, []).append(pydep_local_path)
2094 return ret
2095
2096 def ComputeAffectedPydeps(self):
2097 """Returns an iterable of .pydeps files that might need regenerating."""
2098 affected_pydeps = set()
2099 file_to_pydeps_map = None
2100 for f in self._input_api.AffectedFiles(include_deletes=True):
2101 local_path = f.LocalPath()
2102 if local_path == 'DEPS':
2103 return self._pydeps_files
2104 elif local_path.endswith('.pydeps'):
2105 if local_path in self._pydeps_files:
2106 affected_pydeps.add(local_path)
2107 elif local_path.endswith('.py'):
2108 if file_to_pydeps_map is None:
2109 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2110 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2111 return affected_pydeps
2112
2113 def DetermineIfStale(self, pydeps_path):
2114 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412115 import difflib
John Budorick47ca3fe2018-02-10 00:53:102116 import os
2117
agrievef32bcc72016-04-04 14:57:402118 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2119 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:102120 env = dict(os.environ)
2121 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:402122 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:102123 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412124 old_contents = old_pydeps_data[2:]
2125 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402126 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412127 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402128
2129
2130def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2131 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:402132 # This check is for Python dependency lists (.pydeps files), and involves
2133 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
2134 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:282135 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002136 return []
Mostyn Bramley-Moore6b427322017-12-21 22:11:022137 # TODO(agrieve): Update when there's a better way to detect
2138 # this: crbug.com/570091
agrievef32bcc72016-04-04 14:57:402139 is_android = input_api.os_path.exists('third_party/android_tools')
2140 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2141 results = []
2142 # First, check for new / deleted .pydeps.
2143 for f in input_api.AffectedFiles(include_deletes=True):
2144 if f.LocalPath().endswith('.pydeps'):
2145 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2146 results.append(output_api.PresubmitError(
2147 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2148 'remove %s' % f.LocalPath()))
2149 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2150 results.append(output_api.PresubmitError(
2151 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2152 'include %s' % f.LocalPath()))
2153
2154 if results:
2155 return results
2156
2157 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2158
2159 for pydep_path in checker.ComputeAffectedPydeps():
2160 try:
phajdan.jr0d9878552016-11-04 10:49:412161 result = checker.DetermineIfStale(pydep_path)
2162 if result:
2163 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402164 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412165 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2166 'To regenerate, run:\n\n %s' %
2167 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402168 except input_api.subprocess.CalledProcessError as error:
2169 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2170 long_text=error.output)]
2171
2172 return results
2173
2174
glidere61efad2015-02-18 17:39:432175def _CheckSingletonInHeaders(input_api, output_api):
2176 """Checks to make sure no header files have |Singleton<|."""
2177 def FileFilter(affected_file):
2178 # It's ok for base/memory/singleton.h to have |Singleton<|.
2179 black_list = (_EXCLUDED_PATHS +
2180 input_api.DEFAULT_BLACK_LIST +
2181 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2182 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2183
sergeyu34d21222015-09-16 00:11:442184 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432185 files = []
2186 for f in input_api.AffectedSourceFiles(FileFilter):
2187 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2188 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2189 contents = input_api.ReadFile(f)
2190 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242191 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432192 pattern.search(line)):
2193 files.append(f)
2194 break
2195
2196 if files:
yolandyandaabc6d2016-04-18 18:29:392197 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442198 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432199 'Please move them to an appropriate source file so that the ' +
2200 'template gets instantiated in a single compilation unit.',
2201 files) ]
2202 return []
2203
2204
[email protected]fd20b902014-05-09 02:14:532205_DEPRECATED_CSS = [
2206 # Values
2207 ( "-webkit-box", "flex" ),
2208 ( "-webkit-inline-box", "inline-flex" ),
2209 ( "-webkit-flex", "flex" ),
2210 ( "-webkit-inline-flex", "inline-flex" ),
2211 ( "-webkit-min-content", "min-content" ),
2212 ( "-webkit-max-content", "max-content" ),
2213
2214 # Properties
2215 ( "-webkit-background-clip", "background-clip" ),
2216 ( "-webkit-background-origin", "background-origin" ),
2217 ( "-webkit-background-size", "background-size" ),
2218 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442219 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532220
2221 # Functions
2222 ( "-webkit-gradient", "gradient" ),
2223 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2224 ( "-webkit-linear-gradient", "linear-gradient" ),
2225 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2226 ( "-webkit-radial-gradient", "radial-gradient" ),
2227 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2228]
2229
dbeam1ec68ac2016-12-15 05:22:242230def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532231 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252232 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342233 documentation and iOS CSS for dom distiller
2234 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252235 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532236 results = []
dbeam070cfe62014-10-22 06:44:022237 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252238 black_list = (_EXCLUDED_PATHS +
2239 _TEST_CODE_EXCLUDED_PATHS +
2240 input_api.DEFAULT_BLACK_LIST +
2241 (r"^chrome/common/extensions/docs",
2242 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342243 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442244 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252245 r"^native_client_sdk"))
2246 file_filter = lambda f: input_api.FilterSourceFile(
2247 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532248 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2249 for line_num, line in fpath.ChangedContents():
2250 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022251 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532252 results.append(output_api.PresubmitError(
2253 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2254 (fpath.LocalPath(), line_num, deprecated_value, value)))
2255 return results
2256
mohan.reddyf21db962014-10-16 12:26:472257
dbeam070cfe62014-10-22 06:44:022258_DEPRECATED_JS = [
2259 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2260 ( "__defineGetter__", "Object.defineProperty" ),
2261 ( "__defineSetter__", "Object.defineProperty" ),
2262]
2263
dbeam1ec68ac2016-12-15 05:22:242264def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022265 """Make sure that we don't use deprecated JS in Chrome code."""
2266 results = []
2267 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2268 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2269 input_api.DEFAULT_BLACK_LIST)
2270 file_filter = lambda f: input_api.FilterSourceFile(
2271 f, white_list=file_inclusion_pattern, black_list=black_list)
2272 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2273 for lnum, line in fpath.ChangedContents():
2274 for (deprecated, replacement) in _DEPRECATED_JS:
2275 if deprecated in line:
2276 results.append(output_api.PresubmitError(
2277 "%s:%d: Use of deprecated JS %s, use %s instead" %
2278 (fpath.LocalPath(), lnum, deprecated, replacement)))
2279 return results
2280
dpapadd651231d82017-07-21 02:44:472281def _CheckForRiskyJsArrowFunction(line_number, line):
2282 if ' => ' in line:
2283 return "line %d, is using an => (arrow) function\n %s\n" % (
2284 line_number, line)
2285 return ''
2286
2287def _CheckForRiskyJsConstLet(input_api, line_number, line):
2288 if input_api.re.match('^\s*(const|let)\s', line):
2289 return "line %d, is using const/let keyword\n %s\n" % (
2290 line_number, line)
2291 return ''
dbeam070cfe62014-10-22 06:44:022292
dbeam1ec68ac2016-12-15 05:22:242293def _CheckForRiskyJsFeatures(input_api, output_api):
2294 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002295 # 'ui/webui/resources/cr_components are not allowed on ios'
2296 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572297 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002298 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472299 results = []
dbeam1ec68ac2016-12-15 05:22:242300 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472301 arrow_error_lines = []
2302 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242303 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472304 arrow_error_lines += filter(None, [
2305 _CheckForRiskyJsArrowFunction(lnum, line),
2306 ])
dbeam1ec68ac2016-12-15 05:22:242307
dpapadd651231d82017-07-21 02:44:472308 const_let_error_lines += filter(None, [
2309 _CheckForRiskyJsConstLet(input_api, lnum, line),
2310 ])
dbeam1ec68ac2016-12-15 05:22:242311
dpapadd651231d82017-07-21 02:44:472312 if arrow_error_lines:
2313 arrow_error_lines = map(
2314 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2315 results.append(
2316 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2317"""
2318Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242319%s
2320Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2321https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472322""" % f.LocalPath()
2323 ])))
dbeam1ec68ac2016-12-15 05:22:242324
dpapadd651231d82017-07-21 02:44:472325 if const_let_error_lines:
2326 const_let_error_lines = map(
2327 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2328 results.append(
2329 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2330"""
2331Use of const/let keywords detected in:
2332%s
2333Please ensure your code does not run on iOS9 because const/let is not fully
2334supported.
2335https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2336https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2337""" % f.LocalPath()
2338 ])))
2339
2340 return results
dbeam1ec68ac2016-12-15 05:22:242341
rlanday6802cf632017-05-30 17:48:362342def _CheckForRelativeIncludes(input_api, output_api):
2343 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2344 import sys
2345 original_sys_path = sys.path
2346 try:
2347 sys.path = sys.path + [input_api.os_path.join(
2348 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2349 from cpp_checker import CppChecker
2350 finally:
2351 # Restore sys.path to what it was before.
2352 sys.path = original_sys_path
2353
2354 bad_files = {}
2355 for f in input_api.AffectedFiles(include_deletes=False):
2356 if (f.LocalPath().startswith('third_party') and
2357 not f.LocalPath().startswith('third_party/WebKit') and
2358 not f.LocalPath().startswith('third_party\\WebKit')):
2359 continue
2360
2361 if not CppChecker.IsCppFile(f.LocalPath()):
2362 continue
2363
2364 relative_includes = [line for line_num, line in f.ChangedContents()
2365 if "#include" in line and "../" in line]
2366 if not relative_includes:
2367 continue
2368 bad_files[f.LocalPath()] = relative_includes
2369
2370 if not bad_files:
2371 return []
2372
2373 error_descriptions = []
2374 for file_path, bad_lines in bad_files.iteritems():
2375 error_description = file_path
2376 for line in bad_lines:
2377 error_description += '\n ' + line
2378 error_descriptions.append(error_description)
2379
2380 results = []
2381 results.append(output_api.PresubmitError(
2382 'You added one or more relative #include paths (including "../").\n'
2383 'These shouldn\'t be used because they can be used to include headers\n'
2384 'from code that\'s not correctly specified as a dependency in the\n'
2385 'relevant BUILD.gn file(s).',
2386 error_descriptions))
2387
2388 return results
2389
Takeshi Yoshinoe387aa32017-08-02 13:16:132390
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202391def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2392 if not isinstance(key, ast.Str):
2393 return 'Key at line %d must be a string literal' % key.lineno
2394 if not isinstance(value, ast.Dict):
2395 return 'Value at line %d must be a dict' % value.lineno
2396 if len(value.keys) != 1:
2397 return 'Dict at line %d must have single entry' % value.lineno
2398 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2399 return (
2400 'Entry at line %d must have a string literal \'filepath\' as key' %
2401 value.lineno)
2402 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132403
Takeshi Yoshinoe387aa32017-08-02 13:16:132404
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202405def _CheckWatchlistsEntrySyntax(key, value, ast):
2406 if not isinstance(key, ast.Str):
2407 return 'Key at line %d must be a string literal' % key.lineno
2408 if not isinstance(value, ast.List):
2409 return 'Value at line %d must be a list' % value.lineno
2410 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132411
Takeshi Yoshinoe387aa32017-08-02 13:16:132412
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202413def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2414 mismatch_template = (
2415 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2416 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132417
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202418 i = 0
2419 last_key = ''
2420 while True:
2421 if i >= len(wd_dict.keys):
2422 if i >= len(w_dict.keys):
2423 return None
2424 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2425 elif i >= len(w_dict.keys):
2426 return (
2427 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132428
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202429 wd_key = wd_dict.keys[i]
2430 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132431
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202432 result = _CheckWatchlistDefinitionsEntrySyntax(
2433 wd_key, wd_dict.values[i], ast)
2434 if result is not None:
2435 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132436
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202437 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2438 if result is not None:
2439 return 'Bad entry in WATCHLISTS dict: %s' % result
2440
2441 if wd_key.s != w_key.s:
2442 return mismatch_template % (
2443 '%s at line %d' % (wd_key.s, wd_key.lineno),
2444 '%s at line %d' % (w_key.s, w_key.lineno))
2445
2446 if wd_key.s < last_key:
2447 return (
2448 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2449 (wd_key.lineno, w_key.lineno))
2450 last_key = wd_key.s
2451
2452 i = i + 1
2453
2454
2455def _CheckWATCHLISTSSyntax(expression, ast):
2456 if not isinstance(expression, ast.Expression):
2457 return 'WATCHLISTS file must contain a valid expression'
2458 dictionary = expression.body
2459 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2460 return 'WATCHLISTS file must have single dict with exactly two entries'
2461
2462 first_key = dictionary.keys[0]
2463 first_value = dictionary.values[0]
2464 second_key = dictionary.keys[1]
2465 second_value = dictionary.values[1]
2466
2467 if (not isinstance(first_key, ast.Str) or
2468 first_key.s != 'WATCHLIST_DEFINITIONS' or
2469 not isinstance(first_value, ast.Dict)):
2470 return (
2471 'The first entry of the dict in WATCHLISTS file must be '
2472 'WATCHLIST_DEFINITIONS dict')
2473
2474 if (not isinstance(second_key, ast.Str) or
2475 second_key.s != 'WATCHLISTS' or
2476 not isinstance(second_value, ast.Dict)):
2477 return (
2478 'The second entry of the dict in WATCHLISTS file must be '
2479 'WATCHLISTS dict')
2480
2481 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132482
2483
2484def _CheckWATCHLISTS(input_api, output_api):
2485 for f in input_api.AffectedFiles(include_deletes=False):
2486 if f.LocalPath() == 'WATCHLISTS':
2487 contents = input_api.ReadFile(f, 'r')
2488
2489 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202490 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132491 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202492 # Get an AST tree for it and scan the tree for detailed style checking.
2493 expression = input_api.ast.parse(
2494 contents, filename='WATCHLISTS', mode='eval')
2495 except ValueError as e:
2496 return [output_api.PresubmitError(
2497 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2498 except SyntaxError as e:
2499 return [output_api.PresubmitError(
2500 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2501 except TypeError as e:
2502 return [output_api.PresubmitError(
2503 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132504
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202505 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2506 if result is not None:
2507 return [output_api.PresubmitError(result)]
2508 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132509
2510 return []
2511
2512
dgnaa68d5e2015-06-10 10:08:222513def _AndroidSpecificOnUploadChecks(input_api, output_api):
2514 """Groups checks that target android code."""
2515 results = []
dgnaa68d5e2015-06-10 10:08:222516 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222517 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292518 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062519 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2520 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422521 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182522 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222523 return results
2524
2525
[email protected]22c9bd72011-03-27 16:47:392526def _CommonChecks(input_api, output_api):
2527 """Checks common to both upload and commit."""
2528 results = []
2529 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382530 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542531 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:082532
2533 author = input_api.change.author_email
2534 if author and author not in _KNOWN_ROBOTS:
2535 results.extend(
2536 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
2537
[email protected]55459852011-08-10 15:17:192538 results.extend(
[email protected]760deea2013-12-10 19:33:492539 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542540 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182541 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522542 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222543 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442544 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592545 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062546 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122547 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182548 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222549 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302550 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492551 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032552 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492553 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442554 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272555 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072556 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542557 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442558 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392559 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552560 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042561 results.extend(
2562 input_api.canned_checks.CheckChangeHasNoTabs(
2563 input_api,
2564 output_api,
2565 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402566 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162567 results.extend(_CheckForAnonymousVariables(input_api, output_api))
Peter Kasting4844e46e2018-02-23 07:27:102568 results.extend(_CheckUniquePtr(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082569 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242570 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2571 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472572 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042573 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232574 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432575 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402576 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152577 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172578 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502579 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242580 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362581 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132582 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432583 results.extend(input_api.RunTests(
2584 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242585
2586 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2587 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2588 input_api, output_api,
2589 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382590 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392591 return results
[email protected]1f7b4172010-01-28 01:17:342592
[email protected]b337cb5b2011-01-23 21:24:052593
[email protected]b8079ae4a2012-12-05 19:56:492594def _CheckPatchFiles(input_api, output_api):
2595 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2596 if f.LocalPath().endswith(('.orig', '.rej'))]
2597 if problems:
2598 return [output_api.PresubmitError(
2599 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032600 else:
2601 return []
[email protected]b8079ae4a2012-12-05 19:56:492602
2603
Kent Tamura5a8755d2017-06-29 23:37:072604def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212605 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2606 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2607 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072608 include_re = input_api.re.compile(
2609 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2610 extension_re = input_api.re.compile(r'\.[a-z]+$')
2611 errors = []
2612 for f in input_api.AffectedFiles():
2613 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2614 continue
2615 found_line_number = None
2616 found_macro = None
2617 for line_num, line in f.ChangedContents():
2618 match = macro_re.search(line)
2619 if match:
2620 found_line_number = line_num
2621 found_macro = match.group(2)
2622 break
2623 if not found_line_number:
2624 continue
2625
2626 found_include = False
2627 for line in f.NewContents():
2628 if include_re.search(line):
2629 found_include = True
2630 break
2631 if found_include:
2632 continue
2633
2634 if not f.LocalPath().endswith('.h'):
2635 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2636 try:
2637 content = input_api.ReadFile(primary_header_path, 'r')
2638 if include_re.search(content):
2639 continue
2640 except IOError:
2641 pass
2642 errors.append('%s:%d %s macro is used without including build/'
2643 'build_config.h.'
2644 % (f.LocalPath(), found_line_number, found_macro))
2645 if errors:
2646 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2647 return []
2648
2649
[email protected]b00342e7f2013-03-26 16:21:542650def _DidYouMeanOSMacro(bad_macro):
2651 try:
2652 return {'A': 'OS_ANDROID',
2653 'B': 'OS_BSD',
2654 'C': 'OS_CHROMEOS',
2655 'F': 'OS_FREEBSD',
2656 'L': 'OS_LINUX',
2657 'M': 'OS_MACOSX',
2658 'N': 'OS_NACL',
2659 'O': 'OS_OPENBSD',
2660 'P': 'OS_POSIX',
2661 'S': 'OS_SOLARIS',
2662 'W': 'OS_WIN'}[bad_macro[3].upper()]
2663 except KeyError:
2664 return ''
2665
2666
2667def _CheckForInvalidOSMacrosInFile(input_api, f):
2668 """Check for sensible looking, totally invalid OS macros."""
2669 preprocessor_statement = input_api.re.compile(r'^\s*#')
2670 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2671 results = []
2672 for lnum, line in f.ChangedContents():
2673 if preprocessor_statement.search(line):
2674 for match in os_macro.finditer(line):
2675 if not match.group(1) in _VALID_OS_MACROS:
2676 good = _DidYouMeanOSMacro(match.group(1))
2677 did_you_mean = ' (did you mean %s?)' % good if good else ''
2678 results.append(' %s:%d %s%s' % (f.LocalPath(),
2679 lnum,
2680 match.group(1),
2681 did_you_mean))
2682 return results
2683
2684
2685def _CheckForInvalidOSMacros(input_api, output_api):
2686 """Check all affected files for invalid OS macros."""
2687 bad_macros = []
2688 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472689 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542690 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2691
2692 if not bad_macros:
2693 return []
2694
2695 return [output_api.PresubmitError(
2696 'Possibly invalid OS macro[s] found. Please fix your code\n'
2697 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2698
lliabraa35bab3932014-10-01 12:16:442699
2700def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2701 """Check all affected files for invalid "if defined" macros."""
2702 ALWAYS_DEFINED_MACROS = (
2703 "TARGET_CPU_PPC",
2704 "TARGET_CPU_PPC64",
2705 "TARGET_CPU_68K",
2706 "TARGET_CPU_X86",
2707 "TARGET_CPU_ARM",
2708 "TARGET_CPU_MIPS",
2709 "TARGET_CPU_SPARC",
2710 "TARGET_CPU_ALPHA",
2711 "TARGET_IPHONE_SIMULATOR",
2712 "TARGET_OS_EMBEDDED",
2713 "TARGET_OS_IPHONE",
2714 "TARGET_OS_MAC",
2715 "TARGET_OS_UNIX",
2716 "TARGET_OS_WIN32",
2717 )
2718 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2719 results = []
2720 for lnum, line in f.ChangedContents():
2721 for match in ifdef_macro.finditer(line):
2722 if match.group(1) in ALWAYS_DEFINED_MACROS:
2723 always_defined = ' %s is always defined. ' % match.group(1)
2724 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2725 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2726 lnum,
2727 always_defined,
2728 did_you_mean))
2729 return results
2730
2731
2732def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2733 """Check all affected files for invalid "if defined" macros."""
2734 bad_macros = []
2735 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212736 if f.LocalPath().startswith('third_party/sqlite/'):
2737 continue
lliabraa35bab3932014-10-01 12:16:442738 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2739 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2740
2741 if not bad_macros:
2742 return []
2743
2744 return [output_api.PresubmitError(
2745 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2746 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2747 bad_macros)]
2748
2749
mlamouria82272622014-09-16 18:45:042750def _CheckForIPCRules(input_api, output_api):
2751 """Check for same IPC rules described in
2752 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2753 """
2754 base_pattern = r'IPC_ENUM_TRAITS\('
2755 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2756 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2757
2758 problems = []
2759 for f in input_api.AffectedSourceFiles(None):
2760 local_path = f.LocalPath()
2761 if not local_path.endswith('.h'):
2762 continue
2763 for line_number, line in f.ChangedContents():
2764 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2765 problems.append(
2766 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2767
2768 if problems:
2769 return [output_api.PresubmitPromptWarning(
2770 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2771 else:
2772 return []
2773
[email protected]b00342e7f2013-03-26 16:21:542774
mostynbb639aca52015-01-07 20:31:232775def _CheckForWindowsLineEndings(input_api, output_api):
2776 """Check source code and known ascii text files for Windows style line
2777 endings.
2778 """
earthdok1b5e0ee2015-03-10 15:19:102779 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232780
2781 file_inclusion_pattern = (
2782 known_text_files,
2783 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2784 )
2785
mostynbb639aca52015-01-07 20:31:232786 problems = []
Andrew Grieve933d12e2017-10-30 20:22:532787 source_file_filter = lambda f: input_api.FilterSourceFile(
2788 f, white_list=file_inclusion_pattern, black_list=None)
2789 for f in input_api.AffectedSourceFiles(source_file_filter):
2790 for line_number, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:232791 if line.endswith('\r\n'):
Andrew Grieve933d12e2017-10-30 20:22:532792 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:232793
2794 if problems:
2795 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2796 'these files to contain Windows style line endings?\n' +
2797 '\n'.join(problems))]
2798
2799 return []
2800
2801
pastarmovj89f7ee12016-09-20 14:58:132802def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2803 lint_filters=None, verbose_level=None):
2804 """Checks that all source files use SYSLOG properly."""
2805 syslog_files = []
2806 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562807 for line_number, line in f.ChangedContents():
2808 if 'SYSLOG' in line:
2809 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2810
pastarmovj89f7ee12016-09-20 14:58:132811 if syslog_files:
2812 return [output_api.PresubmitPromptWarning(
2813 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2814 ' calls.\nFiles to check:\n', items=syslog_files)]
2815 return []
2816
2817
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192818def _CheckCrbugLinksHaveHttps(input_api, output_api):
Miguel Casas68bdb652017-12-19 16:29:092819 """Checks that crbug(.com) links are correctly prefixed by https://,
2820 unless they come in the accepted form TODO(crbug.com/...)
2821 """
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192822 white_list = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2823 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS)
2824 sources = lambda f: input_api.FilterSourceFile(
2825 f, white_list=white_list, black_list=black_list)
2826
2827 pattern = input_api.re.compile(r'//.*(?<!:\/\/)crbug[.com]*')
Miguel Casas68bdb652017-12-19 16:29:092828 accepted_pattern = input_api.re.compile(r'//.*TODO\(crbug[.com]*');
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192829 problems = []
2830 for f in input_api.AffectedSourceFiles(sources):
2831 for line_num, line in f.ChangedContents():
Miguel Casas68bdb652017-12-19 16:29:092832 if pattern.search(line) and not accepted_pattern.search(line):
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192833 problems.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2834
2835 if problems:
2836 return [output_api.PresubmitPromptWarning(
2837 'Found unprefixed crbug.com URL(s), consider prepending https://\n'+
2838 '\n'.join(problems))]
2839 return []
2840
2841
[email protected]1f7b4172010-01-28 01:17:342842def CheckChangeOnUpload(input_api, output_api):
2843 results = []
2844 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472845 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282846 results.extend(
jam93a6ee792017-02-08 23:59:222847 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192848 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222849 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132850 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162851 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192852 results.extend(_CheckCrbugLinksHaveHttps(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542853 return results
[email protected]ca8d1982009-02-19 16:33:122854
2855
[email protected]1bfb8322014-04-23 01:02:412856def GetTryServerMasterForBot(bot):
2857 """Returns the Try Server master for the given bot.
2858
[email protected]0bb112362014-07-26 04:38:322859 It tries to guess the master from the bot name, but may still fail
2860 and return None. There is no longer a default master.
2861 """
2862 # Potentially ambiguous bot names are listed explicitly.
2863 master_map = {
tandriie5587792016-07-14 00:34:502864 'chromium_presubmit': 'master.tryserver.chromium.linux',
2865 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412866 }
[email protected]0bb112362014-07-26 04:38:322867 master = master_map.get(bot)
2868 if not master:
wnwen4fbaab82016-05-25 12:54:362869 if 'android' in bot:
tandriie5587792016-07-14 00:34:502870 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362871 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502872 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322873 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502874 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322875 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502876 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322877 return master
[email protected]1bfb8322014-04-23 01:02:412878
2879
[email protected]ca8d1982009-02-19 16:33:122880def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542881 results = []
[email protected]1f7b4172010-01-28 01:17:342882 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542883 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272884 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342885 input_api,
2886 output_api,
[email protected]2fdd1f362013-01-16 03:56:032887 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272888
jam93a6ee792017-02-08 23:59:222889 results.extend(
2890 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542891 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2892 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412893 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2894 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542895 return results