blob: e7b82ae46383a09f276fb310d389faf7dcc9b2d1 [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 ),
[email protected]127f18ec2012-06-16 05:05:59459)
460
wnwenbdc444e2016-05-25 13:44:15461
mlamouria82272622014-09-16 18:45:04462_IPC_ENUM_TRAITS_DEPRECATED = (
463 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
464 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
465
Shenghua Zhangbfaa38b82017-11-16 21:58:02466_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
467 r".*[\\\/]BuildHooksAndroidImpl\.java",
468 r".*[\\\/]LicenseContentProvider\.java",
469]
[email protected]127f18ec2012-06-16 05:05:59470
Sean Kau46e29bc2017-08-28 16:31:16471# These paths contain test data and other known invalid JSON files.
472_KNOWN_INVALID_JSON_FILE_PATTERNS = [
473 r'test[\\\/]data[\\\/]',
474 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
475 r'^third_party[\\\/]protobuf[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16476 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Sean Kau46e29bc2017-08-28 16:31:16477]
478
479
[email protected]b00342e7f2013-03-26 16:21:54480_VALID_OS_MACROS = (
481 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08482 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54483 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:12484 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:54485 'OS_BSD',
486 'OS_CAT', # For testing.
487 'OS_CHROMEOS',
488 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37489 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54490 'OS_IOS',
491 'OS_LINUX',
492 'OS_MACOSX',
493 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21494 'OS_NACL_NONSFI',
495 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12496 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54497 'OS_OPENBSD',
498 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37499 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54500 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54501 'OS_WIN',
502)
503
504
agrievef32bcc72016-04-04 14:57:40505_ANDROID_SPECIFIC_PYDEPS_FILES = [
506 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04507 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58508 'build/secondary/third_party/android_platform/'
509 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19510 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40511]
512
wnwenbdc444e2016-05-25 13:44:15513
agrievef32bcc72016-04-04 14:57:40514_GENERIC_PYDEPS_FILES = [
John Chencde89192018-01-27 21:18:40515 'chrome/test/chromedriver/test/run_py_tests.pydeps',
agrievef32bcc72016-04-04 14:57:40516]
517
wnwenbdc444e2016-05-25 13:44:15518
agrievef32bcc72016-04-04 14:57:40519_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
520
521
Eric Boren6fd2b932018-01-25 15:05:08522# Bypass the AUTHORS check for these accounts.
523_KNOWN_ROBOTS = set(
524 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
Eric Borenf88aa2e2018-01-30 16:11:24525 for s in ('angle', 'catapult', 'depot-tools', 'nacl', 'pdfium', 'skia',
526 'src-internal', 'webrtc'))
Eric Boren6fd2b932018-01-25 15:05:08527
528
[email protected]55459852011-08-10 15:17:19529def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
530 """Attempts to prevent use of functions intended only for testing in
531 non-testing code. For now this is just a best-effort implementation
532 that ignores header files and may have some false positives. A
533 better implementation would probably need a proper C++ parser.
534 """
535 # We only scan .cc files and the like, as the declaration of
536 # for-testing functions in header files are hard to distinguish from
537 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44538 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19539
jochenc0d4808c2015-07-27 09:25:42540 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19541 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09542 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19543 exclusion_pattern = input_api.re.compile(
544 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
545 base_function_pattern, base_function_pattern))
546
547 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44548 black_list = (_EXCLUDED_PATHS +
549 _TEST_CODE_EXCLUDED_PATHS +
550 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19551 return input_api.FilterSourceFile(
552 affected_file,
553 white_list=(file_inclusion_pattern, ),
554 black_list=black_list)
555
556 problems = []
557 for f in input_api.AffectedSourceFiles(FilterFile):
558 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24559 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03560 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46561 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03562 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19563 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03564 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19565
566 if problems:
[email protected]f7051d52013-04-02 18:31:42567 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03568 else:
569 return []
[email protected]55459852011-08-10 15:17:19570
571
[email protected]10689ca2011-09-02 02:31:54572def _CheckNoIOStreamInHeaders(input_api, output_api):
573 """Checks to make sure no .h files include <iostream>."""
574 files = []
575 pattern = input_api.re.compile(r'^#include\s*<iostream>',
576 input_api.re.MULTILINE)
577 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
578 if not f.LocalPath().endswith('.h'):
579 continue
580 contents = input_api.ReadFile(f)
581 if pattern.search(contents):
582 files.append(f)
583
584 if len(files):
yolandyandaabc6d2016-04-18 18:29:39585 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06586 'Do not #include <iostream> in header files, since it inserts static '
587 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54588 '#include <ostream>. See http://crbug.com/94794',
589 files) ]
590 return []
591
592
[email protected]72df4e782012-06-21 16:28:18593def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52594 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18595 problems = []
596 for f in input_api.AffectedFiles():
597 if (not f.LocalPath().endswith(('.cc', '.mm'))):
598 continue
599
600 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04601 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18602 problems.append(' %s:%d' % (f.LocalPath(), line_num))
603
604 if not problems:
605 return []
606 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
607 '\n'.join(problems))]
608
609
danakj61c1aa22015-10-26 19:55:52610def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57611 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52612 errors = []
613 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
614 input_api.re.MULTILINE)
615 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
616 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
617 continue
618 for lnum, line in f.ChangedContents():
619 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17620 errors.append(output_api.PresubmitError(
621 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57622 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17623 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52624 return errors
625
626
mcasasb7440c282015-02-04 14:52:19627def _FindHistogramNameInLine(histogram_name, line):
628 """Tries to find a histogram name or prefix in a line."""
629 if not "affected-histogram" in line:
630 return histogram_name in line
631 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
632 # the histogram_name.
633 if not '"' in line:
634 return False
635 histogram_prefix = line.split('\"')[1]
636 return histogram_prefix in histogram_name
637
638
639def _CheckUmaHistogramChanges(input_api, output_api):
640 """Check that UMA histogram names in touched lines can still be found in other
641 lines of the patch or in histograms.xml. Note that this check would not catch
642 the reverse: changes in histograms.xml not matched in the code itself."""
643 touched_histograms = []
644 histograms_xml_modifications = []
645 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
646 for f in input_api.AffectedFiles():
647 # If histograms.xml itself is modified, keep the modified lines for later.
648 if f.LocalPath().endswith(('histograms.xml')):
649 histograms_xml_modifications = f.ChangedContents()
650 continue
651 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
652 continue
653 for line_num, line in f.ChangedContents():
654 found = pattern.search(line)
655 if found:
656 touched_histograms.append([found.group(1), f, line_num])
657
658 # Search for the touched histogram names in the local modifications to
659 # histograms.xml, and, if not found, on the base histograms.xml file.
660 unmatched_histograms = []
661 for histogram_info in touched_histograms:
662 histogram_name_found = False
663 for line_num, line in histograms_xml_modifications:
664 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
665 if histogram_name_found:
666 break
667 if not histogram_name_found:
668 unmatched_histograms.append(histogram_info)
669
eromanb90c82e7e32015-04-01 15:13:49670 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19671 problems = []
672 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49673 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19674 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45675 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19676 histogram_name_found = False
677 for line in histograms_xml:
678 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
679 if histogram_name_found:
680 break
681 if not histogram_name_found:
682 problems.append(' [%s:%d] %s' %
683 (f.LocalPath(), line_num, histogram_name))
684
685 if not problems:
686 return []
687 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
688 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49689 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19690
wnwenbdc444e2016-05-25 13:44:15691
yolandyandaabc6d2016-04-18 18:29:39692def _CheckFlakyTestUsage(input_api, output_api):
693 """Check that FlakyTest annotation is our own instead of the android one"""
694 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
695 files = []
696 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
697 if f.LocalPath().endswith('Test.java'):
698 if pattern.search(input_api.ReadFile(f)):
699 files.append(f)
700 if len(files):
701 return [output_api.PresubmitError(
702 'Use org.chromium.base.test.util.FlakyTest instead of '
703 'android.test.FlakyTest',
704 files)]
705 return []
mcasasb7440c282015-02-04 14:52:19706
wnwenbdc444e2016-05-25 13:44:15707
[email protected]8ea5d4b2011-09-13 21:49:22708def _CheckNoNewWStrings(input_api, output_api):
709 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27710 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22711 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20712 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57713 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34714 '/win/' in f.LocalPath() or
715 'chrome_elf' in f.LocalPath() or
716 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20717 continue
[email protected]8ea5d4b2011-09-13 21:49:22718
[email protected]a11dbe9b2012-08-07 01:32:58719 allowWString = False
[email protected]b5c24292011-11-28 14:38:20720 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58721 if 'presubmit: allow wstring' in line:
722 allowWString = True
723 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27724 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58725 allowWString = False
726 else:
727 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22728
[email protected]55463aa62011-10-12 00:48:27729 if not problems:
730 return []
731 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58732 ' If you are calling a cross-platform API that accepts a wstring, '
733 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27734 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22735
736
[email protected]2a8ac9c2011-10-19 17:20:44737def _CheckNoDEPSGIT(input_api, output_api):
738 """Make sure .DEPS.git is never modified manually."""
739 if any(f.LocalPath().endswith('.DEPS.git') for f in
740 input_api.AffectedFiles()):
741 return [output_api.PresubmitError(
742 'Never commit changes to .DEPS.git. This file is maintained by an\n'
743 'automated system based on what\'s in DEPS and your changes will be\n'
744 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34745 '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:44746 'for more information')]
747 return []
748
749
tandriief664692014-09-23 14:51:47750def _CheckValidHostsInDEPS(input_api, output_api):
751 """Checks that DEPS file deps are from allowed_hosts."""
752 # Run only if DEPS file has been modified to annoy fewer bystanders.
753 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
754 return []
755 # Outsource work to gclient verify
756 try:
757 input_api.subprocess.check_output(['gclient', 'verify'])
758 return []
759 except input_api.subprocess.CalledProcessError, error:
760 return [output_api.PresubmitError(
761 'DEPS file must have only git dependencies.',
762 long_text=error.output)]
763
764
[email protected]127f18ec2012-06-16 05:05:59765def _CheckNoBannedFunctions(input_api, output_api):
766 """Make sure that banned functions are not used."""
767 warnings = []
768 errors = []
769
wnwenbdc444e2016-05-25 13:44:15770 def IsBlacklisted(affected_file, blacklist):
771 local_path = affected_file.LocalPath()
772 for item in blacklist:
773 if input_api.re.match(item, local_path):
774 return True
775 return False
776
777 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
778 matched = False
779 if func_name[0:1] == '/':
780 regex = func_name[1:]
781 if input_api.re.search(regex, line):
782 matched = True
783 elif func_name in line:
dchenge07de812016-06-20 19:27:17784 matched = True
wnwenbdc444e2016-05-25 13:44:15785 if matched:
dchenge07de812016-06-20 19:27:17786 problems = warnings
wnwenbdc444e2016-05-25 13:44:15787 if error:
dchenge07de812016-06-20 19:27:17788 problems = errors
wnwenbdc444e2016-05-25 13:44:15789 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
790 for message_line in message:
791 problems.append(' %s' % message_line)
792
Eric Stevensona9a980972017-09-23 00:04:41793 file_filter = lambda f: f.LocalPath().endswith(('.java'))
794 for f in input_api.AffectedFiles(file_filter=file_filter):
795 for line_num, line in f.ChangedContents():
796 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
797 CheckForMatch(f, line_num, line, func_name, message, error)
798
[email protected]127f18ec2012-06-16 05:05:59799 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
800 for f in input_api.AffectedFiles(file_filter=file_filter):
801 for line_num, line in f.ChangedContents():
802 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15803 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59804
805 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
806 for f in input_api.AffectedFiles(file_filter=file_filter):
807 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49808 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49809 if IsBlacklisted(f, excluded_paths):
810 continue
wnwenbdc444e2016-05-25 13:44:15811 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59812
813 result = []
814 if (warnings):
815 result.append(output_api.PresubmitPromptWarning(
816 'Banned functions were used.\n' + '\n'.join(warnings)))
817 if (errors):
818 result.append(output_api.PresubmitError(
819 'Banned functions were used.\n' + '\n'.join(errors)))
820 return result
821
822
[email protected]6c063c62012-07-11 19:11:06823def _CheckNoPragmaOnce(input_api, output_api):
824 """Make sure that banned functions are not used."""
825 files = []
826 pattern = input_api.re.compile(r'^#pragma\s+once',
827 input_api.re.MULTILINE)
828 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
829 if not f.LocalPath().endswith('.h'):
830 continue
831 contents = input_api.ReadFile(f)
832 if pattern.search(contents):
833 files.append(f)
834
835 if files:
836 return [output_api.PresubmitError(
837 'Do not use #pragma once in header files.\n'
838 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
839 files)]
840 return []
841
[email protected]127f18ec2012-06-16 05:05:59842
[email protected]e7479052012-09-19 00:26:12843def _CheckNoTrinaryTrueFalse(input_api, output_api):
844 """Checks to make sure we don't introduce use of foo ? true : false."""
845 problems = []
846 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
847 for f in input_api.AffectedFiles():
848 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
849 continue
850
851 for line_num, line in f.ChangedContents():
852 if pattern.match(line):
853 problems.append(' %s:%d' % (f.LocalPath(), line_num))
854
855 if not problems:
856 return []
857 return [output_api.PresubmitPromptWarning(
858 'Please consider avoiding the "? true : false" pattern if possible.\n' +
859 '\n'.join(problems))]
860
861
[email protected]55f9f382012-07-31 11:02:18862def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28863 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18864 change. Breaking - rules is an error, breaking ! rules is a
865 warning.
866 """
mohan.reddyf21db962014-10-16 12:26:47867 import sys
[email protected]55f9f382012-07-31 11:02:18868 # We need to wait until we have an input_api object and use this
869 # roundabout construct to import checkdeps because this file is
870 # eval-ed and thus doesn't have __file__.
871 original_sys_path = sys.path
872 try:
873 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47874 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18875 import checkdeps
876 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:24877 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:28878 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18879 from rules import Rule
880 finally:
881 # Restore sys.path to what it was before.
882 sys.path = original_sys_path
883
884 added_includes = []
rhalavati08acd232017-04-03 07:23:28885 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:24886 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:18887 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28888 if CppChecker.IsCppFile(f.LocalPath()):
889 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08890 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:28891 elif ProtoChecker.IsProtoFile(f.LocalPath()):
892 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08893 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:24894 elif JavaChecker.IsJavaFile(f.LocalPath()):
895 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08896 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18897
[email protected]26385172013-05-09 23:11:35898 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18899
900 error_descriptions = []
901 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28902 error_subjects = set()
903 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18904 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
905 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:08906 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18907 description_with_path = '%s\n %s' % (path, rule_description)
908 if rule_type == Rule.DISALLOW:
909 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28910 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18911 else:
912 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28913 warning_subjects.add("#includes")
914
915 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
916 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:08917 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:28918 description_with_path = '%s\n %s' % (path, rule_description)
919 if rule_type == Rule.DISALLOW:
920 error_descriptions.append(description_with_path)
921 error_subjects.add("imports")
922 else:
923 warning_descriptions.append(description_with_path)
924 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18925
Jinsuk Kim5a092672017-10-24 22:42:24926 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:02927 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:08928 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:24929 description_with_path = '%s\n %s' % (path, rule_description)
930 if rule_type == Rule.DISALLOW:
931 error_descriptions.append(description_with_path)
932 error_subjects.add("imports")
933 else:
934 warning_descriptions.append(description_with_path)
935 warning_subjects.add("imports")
936
[email protected]55f9f382012-07-31 11:02:18937 results = []
938 if error_descriptions:
939 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28940 'You added one or more %s that violate checkdeps rules.'
941 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18942 error_descriptions))
943 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42944 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28945 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18946 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28947 '%s? See relevant DEPS file(s) for details and contacts.' %
948 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18949 warning_descriptions))
950 return results
951
952
[email protected]fbcafe5a2012-08-08 15:31:22953def _CheckFilePermissions(input_api, output_api):
954 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15955 if input_api.platform == 'win32':
956 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29957 checkperms_tool = input_api.os_path.join(
958 input_api.PresubmitLocalPath(),
959 'tools', 'checkperms', 'checkperms.py')
960 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47961 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:39962 with input_api.CreateTemporaryFile() as file_list:
963 for f in input_api.AffectedFiles():
964 # checkperms.py file/directory arguments must be relative to the
965 # repository.
966 file_list.write(f.LocalPath() + '\n')
967 file_list.close()
968 args += ['--file-list', file_list.name]
969 try:
970 input_api.subprocess.check_output(args)
971 return []
972 except input_api.subprocess.CalledProcessError as error:
973 return [output_api.PresubmitError(
974 'checkperms.py failed:',
975 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22976
977
robertocn832f5992017-01-04 19:01:30978def _CheckTeamTags(input_api, output_api):
979 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
980 checkteamtags_tool = input_api.os_path.join(
981 input_api.PresubmitLocalPath(),
982 'tools', 'checkteamtags', 'checkteamtags.py')
983 args = [input_api.python_executable, checkteamtags_tool,
984 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22985 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30986 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
987 'OWNERS']
988 try:
989 if files:
990 input_api.subprocess.check_output(args + files)
991 return []
992 except input_api.subprocess.CalledProcessError as error:
993 return [output_api.PresubmitError(
994 'checkteamtags.py failed:',
995 long_text=error.output)]
996
997
[email protected]c8278b32012-10-30 20:35:49998def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
999 """Makes sure we don't include ui/aura/window_property.h
1000 in header files.
1001 """
1002 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1003 errors = []
1004 for f in input_api.AffectedFiles():
1005 if not f.LocalPath().endswith('.h'):
1006 continue
1007 for line_num, line in f.ChangedContents():
1008 if pattern.match(line):
1009 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1010
1011 results = []
1012 if errors:
1013 results.append(output_api.PresubmitError(
1014 'Header files should not include ui/aura/window_property.h', errors))
1015 return results
1016
1017
[email protected]70ca77752012-11-20 03:45:031018def _CheckForVersionControlConflictsInFile(input_api, f):
1019 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1020 errors = []
1021 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231022 if f.LocalPath().endswith('.md'):
1023 # First-level headers in markdown look a lot like version control
1024 # conflict markers. http://daringfireball.net/projects/markdown/basics
1025 continue
[email protected]70ca77752012-11-20 03:45:031026 if pattern.match(line):
1027 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1028 return errors
1029
1030
1031def _CheckForVersionControlConflicts(input_api, output_api):
1032 """Usually this is not intentional and will cause a compile failure."""
1033 errors = []
1034 for f in input_api.AffectedFiles():
1035 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1036
1037 results = []
1038 if errors:
1039 results.append(output_api.PresubmitError(
1040 'Version control conflict markers found, please resolve.', errors))
1041 return results
1042
estadee17314a02017-01-12 16:22:161043def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1044 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1045 errors = []
1046 for f in input_api.AffectedFiles():
1047 for line_num, line in f.ChangedContents():
1048 if pattern.search(line):
1049 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1050
1051 results = []
1052 if errors:
1053 results.append(output_api.PresubmitPromptWarning(
1054 'Found Google support URL addressed by answer number. Please replace with '
1055 'a p= identifier instead. See crbug.com/679462\n', errors))
1056 return results
1057
[email protected]70ca77752012-11-20 03:45:031058
[email protected]06e6d0ff2012-12-11 01:36:441059def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1060 def FilterFile(affected_file):
1061 """Filter function for use with input_api.AffectedSourceFiles,
1062 below. This filters out everything except non-test files from
1063 top-level directories that generally speaking should not hard-code
1064 service URLs (e.g. src/android_webview/, src/content/ and others).
1065 """
1066 return input_api.FilterSourceFile(
1067 affected_file,
[email protected]78bb39d62012-12-11 15:11:561068 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441069 black_list=(_EXCLUDED_PATHS +
1070 _TEST_CODE_EXCLUDED_PATHS +
1071 input_api.DEFAULT_BLACK_LIST))
1072
reillyi38965732015-11-16 18:27:331073 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1074 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461075 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1076 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441077 problems = [] # items are (filename, line_number, line)
1078 for f in input_api.AffectedSourceFiles(FilterFile):
1079 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461080 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441081 problems.append((f.LocalPath(), line_num, line))
1082
1083 if problems:
[email protected]f7051d52013-04-02 18:31:421084 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441085 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581086 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441087 [' %s:%d: %s' % (
1088 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031089 else:
1090 return []
[email protected]06e6d0ff2012-12-11 01:36:441091
1092
[email protected]d2530012013-01-25 16:39:271093def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1094 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311095 The native_client_sdk directory is excluded because it has auto-generated PNG
1096 files for documentation.
[email protected]d2530012013-01-25 16:39:271097 """
[email protected]d2530012013-01-25 16:39:271098 errors = []
binji0dcdf342014-12-12 18:32:311099 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1100 black_list = (r'^native_client_sdk[\\\/]',)
1101 file_filter = lambda f: input_api.FilterSourceFile(
1102 f, white_list=white_list, black_list=black_list)
1103 for f in input_api.AffectedFiles(include_deletes=False,
1104 file_filter=file_filter):
1105 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271106
1107 results = []
1108 if errors:
1109 results.append(output_api.PresubmitError(
1110 'The name of PNG files should not have abbreviations. \n'
1111 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1112 'Contact [email protected] if you have questions.', errors))
1113 return results
1114
1115
Daniel Cheng4dcdb6b2017-04-13 08:30:171116def _ExtractAddRulesFromParsedDeps(parsed_deps):
1117 """Extract the rules that add dependencies from a parsed DEPS file.
1118
1119 Args:
1120 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1121 add_rules = set()
1122 add_rules.update([
1123 rule[1:] for rule in parsed_deps.get('include_rules', [])
1124 if rule.startswith('+') or rule.startswith('!')
1125 ])
1126 for specific_file, rules in parsed_deps.get('specific_include_rules',
1127 {}).iteritems():
1128 add_rules.update([
1129 rule[1:] for rule in rules
1130 if rule.startswith('+') or rule.startswith('!')
1131 ])
1132 return add_rules
1133
1134
1135def _ParseDeps(contents):
1136 """Simple helper for parsing DEPS files."""
1137 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171138 class _VarImpl:
1139
1140 def __init__(self, local_scope):
1141 self._local_scope = local_scope
1142
1143 def Lookup(self, var_name):
1144 """Implements the Var syntax."""
1145 try:
1146 return self._local_scope['vars'][var_name]
1147 except KeyError:
1148 raise Exception('Var is not defined: %s' % var_name)
1149
1150 local_scope = {}
1151 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171152 'Var': _VarImpl(local_scope).Lookup,
1153 }
1154 exec contents in global_scope, local_scope
1155 return local_scope
1156
1157
1158def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081159 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411160 a set of DEPS entries that we should look up.
1161
1162 For a directory (rather than a specific filename) we fake a path to
1163 a specific filename by adding /DEPS. This is chosen as a file that
1164 will seldom or never be subject to per-file include_rules.
1165 """
[email protected]2b438d62013-11-14 17:54:141166 # We ignore deps entries on auto-generated directories.
1167 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081168
Daniel Cheng4dcdb6b2017-04-13 08:30:171169 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1170 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1171
1172 added_deps = new_deps.difference(old_deps)
1173
[email protected]2b438d62013-11-14 17:54:141174 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171175 for added_dep in added_deps:
1176 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1177 continue
1178 # Assume that a rule that ends in .h is a rule for a specific file.
1179 if added_dep.endswith('.h'):
1180 results.add(added_dep)
1181 else:
1182 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081183 return results
1184
1185
[email protected]e871964c2013-05-13 14:14:551186def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1187 """When a dependency prefixed with + is added to a DEPS file, we
1188 want to make sure that the change is reviewed by an OWNER of the
1189 target file or directory, to avoid layering violations from being
1190 introduced. This check verifies that this happens.
1191 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171192 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241193
1194 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191195 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241196 for f in input_api.AffectedFiles(include_deletes=False,
1197 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551198 filename = input_api.os_path.basename(f.LocalPath())
1199 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171200 virtual_depended_on_files.update(_CalculateAddedDeps(
1201 input_api.os_path,
1202 '\n'.join(f.OldContents()),
1203 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551204
[email protected]e871964c2013-05-13 14:14:551205 if not virtual_depended_on_files:
1206 return []
1207
1208 if input_api.is_committing:
1209 if input_api.tbr:
1210 return [output_api.PresubmitNotifyResult(
1211 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271212 if input_api.dry_run:
1213 return [output_api.PresubmitNotifyResult(
1214 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551215 if not input_api.change.issue:
1216 return [output_api.PresubmitError(
1217 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401218 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551219 output = output_api.PresubmitError
1220 else:
1221 output = output_api.PresubmitNotifyResult
1222
1223 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501224 owner_email, reviewers = (
1225 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1226 input_api,
1227 owners_db.email_regexp,
1228 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551229
1230 owner_email = owner_email or input_api.change.author_email
1231
[email protected]de4f7d22013-05-23 14:27:461232 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511233 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461234 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551235 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1236 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411237
1238 # We strip the /DEPS part that was added by
1239 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1240 # directory.
1241 def StripDeps(path):
1242 start_deps = path.rfind('/DEPS')
1243 if start_deps != -1:
1244 return path[:start_deps]
1245 else:
1246 return path
1247 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551248 for path in missing_files]
1249
1250 if unapproved_dependencies:
1251 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151252 output('You need LGTM from owners of depends-on paths in DEPS that were '
1253 'modified in this CL:\n %s' %
1254 '\n '.join(sorted(unapproved_dependencies)))]
1255 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1256 output_list.append(output(
1257 'Suggested missing target path OWNERS:\n %s' %
1258 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551259 return output_list
1260
1261 return []
1262
1263
[email protected]85218562013-11-22 07:41:401264def _CheckSpamLogging(input_api, output_api):
1265 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1266 black_list = (_EXCLUDED_PATHS +
1267 _TEST_CODE_EXCLUDED_PATHS +
1268 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501269 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191270 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481271 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461272 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121273 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1274 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581275 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591276 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161277 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031278 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151279 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1280 r"^chromecast[\\\/]",
1281 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481282 r"^components[\\\/]browser_watcher[\\\/]"
1283 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311284 r"^components[\\\/]html_viewer[\\\/]"
1285 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461286 # TODO(peter): Remove this exception. https://crbug.com/534537
1287 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1288 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251289 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1290 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241291 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111292 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151293 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111294 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521295 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501296 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361297 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311298 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131299 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001300 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441301 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451302 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021303 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351304 r"dump_file_system.cc$",
1305 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401306 source_file_filter = lambda x: input_api.FilterSourceFile(
1307 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1308
thomasanderson625d3932017-03-29 07:16:581309 log_info = set([])
1310 printf = set([])
[email protected]85218562013-11-22 07:41:401311
1312 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581313 for _, line in f.ChangedContents():
1314 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1315 log_info.add(f.LocalPath())
1316 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1317 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371318
thomasanderson625d3932017-03-29 07:16:581319 if input_api.re.search(r"\bprintf\(", line):
1320 printf.add(f.LocalPath())
1321 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1322 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401323
1324 if log_info:
1325 return [output_api.PresubmitError(
1326 'These files spam the console log with LOG(INFO):',
1327 items=log_info)]
1328 if printf:
1329 return [output_api.PresubmitError(
1330 'These files spam the console log with printf/fprintf:',
1331 items=printf)]
1332 return []
1333
1334
[email protected]49aa76a2013-12-04 06:59:161335def _CheckForAnonymousVariables(input_api, output_api):
1336 """These types are all expected to hold locks while in scope and
1337 so should never be anonymous (which causes them to be immediately
1338 destroyed)."""
1339 they_who_must_be_named = [
1340 'base::AutoLock',
1341 'base::AutoReset',
1342 'base::AutoUnlock',
1343 'SkAutoAlphaRestore',
1344 'SkAutoBitmapShaderInstall',
1345 'SkAutoBlitterChoose',
1346 'SkAutoBounderCommit',
1347 'SkAutoCallProc',
1348 'SkAutoCanvasRestore',
1349 'SkAutoCommentBlock',
1350 'SkAutoDescriptor',
1351 'SkAutoDisableDirectionCheck',
1352 'SkAutoDisableOvalCheck',
1353 'SkAutoFree',
1354 'SkAutoGlyphCache',
1355 'SkAutoHDC',
1356 'SkAutoLockColors',
1357 'SkAutoLockPixels',
1358 'SkAutoMalloc',
1359 'SkAutoMaskFreeImage',
1360 'SkAutoMutexAcquire',
1361 'SkAutoPathBoundsUpdate',
1362 'SkAutoPDFRelease',
1363 'SkAutoRasterClipValidate',
1364 'SkAutoRef',
1365 'SkAutoTime',
1366 'SkAutoTrace',
1367 'SkAutoUnref',
1368 ]
1369 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1370 # bad: base::AutoLock(lock.get());
1371 # not bad: base::AutoLock lock(lock.get());
1372 bad_pattern = input_api.re.compile(anonymous)
1373 # good: new base::AutoLock(lock.get())
1374 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1375 errors = []
1376
1377 for f in input_api.AffectedFiles():
1378 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1379 continue
1380 for linenum, line in f.ChangedContents():
1381 if bad_pattern.search(line) and not good_pattern.search(line):
1382 errors.append('%s:%d' % (f.LocalPath(), linenum))
1383
1384 if errors:
1385 return [output_api.PresubmitError(
1386 'These lines create anonymous variables that need to be named:',
1387 items=errors)]
1388 return []
1389
1390
[email protected]999261d2014-03-03 20:08:081391def _CheckUserActionUpdate(input_api, output_api):
1392 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521393 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081394 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521395 # If actions.xml is already included in the changelist, the PRESUBMIT
1396 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081397 return []
1398
[email protected]999261d2014-03-03 20:08:081399 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1400 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521401 current_actions = None
[email protected]999261d2014-03-03 20:08:081402 for f in input_api.AffectedFiles(file_filter=file_filter):
1403 for line_num, line in f.ChangedContents():
1404 match = input_api.re.search(action_re, line)
1405 if match:
[email protected]2f92dec2014-03-07 19:21:521406 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1407 # loaded only once.
1408 if not current_actions:
1409 with open('tools/metrics/actions/actions.xml') as actions_f:
1410 current_actions = actions_f.read()
1411 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081412 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521413 action = 'name="{0}"'.format(action_name)
1414 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081415 return [output_api.PresubmitPromptWarning(
1416 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521417 'tools/metrics/actions/actions.xml. Please run '
1418 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081419 % (f.LocalPath(), line_num, action_name))]
1420 return []
1421
1422
Daniel Cheng13ca61a882017-08-25 15:11:251423def _ImportJSONCommentEater(input_api):
1424 import sys
1425 sys.path = sys.path + [input_api.os_path.join(
1426 input_api.PresubmitLocalPath(),
1427 'tools', 'json_comment_eater')]
1428 import json_comment_eater
1429 return json_comment_eater
1430
1431
[email protected]99171a92014-06-03 08:44:471432def _GetJSONParseError(input_api, filename, eat_comments=True):
1433 try:
1434 contents = input_api.ReadFile(filename)
1435 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251436 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131437 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471438
1439 input_api.json.loads(contents)
1440 except ValueError as e:
1441 return e
1442 return None
1443
1444
1445def _GetIDLParseError(input_api, filename):
1446 try:
1447 contents = input_api.ReadFile(filename)
1448 idl_schema = input_api.os_path.join(
1449 input_api.PresubmitLocalPath(),
1450 'tools', 'json_schema_compiler', 'idl_schema.py')
1451 process = input_api.subprocess.Popen(
1452 [input_api.python_executable, idl_schema],
1453 stdin=input_api.subprocess.PIPE,
1454 stdout=input_api.subprocess.PIPE,
1455 stderr=input_api.subprocess.PIPE,
1456 universal_newlines=True)
1457 (_, error) = process.communicate(input=contents)
1458 return error or None
1459 except ValueError as e:
1460 return e
1461
1462
1463def _CheckParseErrors(input_api, output_api):
1464 """Check that IDL and JSON files do not contain syntax errors."""
1465 actions = {
1466 '.idl': _GetIDLParseError,
1467 '.json': _GetJSONParseError,
1468 }
[email protected]99171a92014-06-03 08:44:471469 # Most JSON files are preprocessed and support comments, but these do not.
1470 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491471 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471472 ]
1473 # Only run IDL checker on files in these directories.
1474 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491475 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1476 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471477 ]
1478
1479 def get_action(affected_file):
1480 filename = affected_file.LocalPath()
1481 return actions.get(input_api.os_path.splitext(filename)[1])
1482
[email protected]99171a92014-06-03 08:44:471483 def FilterFile(affected_file):
1484 action = get_action(affected_file)
1485 if not action:
1486 return False
1487 path = affected_file.LocalPath()
1488
Sean Kau46e29bc2017-08-28 16:31:161489 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471490 return False
1491
1492 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161493 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471494 return False
1495 return True
1496
1497 results = []
1498 for affected_file in input_api.AffectedFiles(
1499 file_filter=FilterFile, include_deletes=False):
1500 action = get_action(affected_file)
1501 kwargs = {}
1502 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161503 _MatchesFile(input_api, json_no_comments_patterns,
1504 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471505 kwargs['eat_comments'] = False
1506 parse_error = action(input_api,
1507 affected_file.AbsoluteLocalPath(),
1508 **kwargs)
1509 if parse_error:
1510 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1511 (affected_file.LocalPath(), parse_error)))
1512 return results
1513
1514
[email protected]760deea2013-12-10 19:33:491515def _CheckJavaStyle(input_api, output_api):
1516 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471517 import sys
[email protected]760deea2013-12-10 19:33:491518 original_sys_path = sys.path
1519 try:
1520 sys.path = sys.path + [input_api.os_path.join(
1521 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1522 import checkstyle
1523 finally:
1524 # Restore sys.path to what it was before.
1525 sys.path = original_sys_path
1526
1527 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091528 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511529 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491530
1531
Sean Kau46e29bc2017-08-28 16:31:161532def _MatchesFile(input_api, patterns, path):
1533 for pattern in patterns:
1534 if input_api.re.search(pattern, path):
1535 return True
1536 return False
1537
1538
Daniel Cheng7052cdf2017-11-21 19:23:291539def _GetOwnersFilesToCheckForIpcOwners(input_api):
1540 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:171541
Daniel Cheng7052cdf2017-11-21 19:23:291542 Returns:
1543 A dictionary mapping an OWNER file to the list of OWNERS rules it must
1544 contain to cover IPC-related files with noparent reviewer rules.
1545 """
1546 # Whether or not a file affects IPC is (mostly) determined by a simple list
1547 # of filename patterns.
dchenge07de812016-06-20 19:27:171548 file_patterns = [
palmerb19a0932017-01-24 04:00:311549 # Legacy IPC:
dchenge07de812016-06-20 19:27:171550 '*_messages.cc',
1551 '*_messages*.h',
1552 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311553 # Mojo IPC:
dchenge07de812016-06-20 19:27:171554 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:471555 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:171556 '*_struct_traits*.*',
1557 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311558 '*.typemap',
1559 # Android native IPC:
1560 '*.aidl',
1561 # Blink uses a different file naming convention:
1562 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:471563 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:171564 '*StructTraits*.*',
1565 '*TypeConverter*.*',
1566 ]
1567
scottmg7a6ed5ba2016-11-04 18:22:041568 # These third_party directories do not contain IPCs, but contain files
1569 # matching the above patterns, which trigger false positives.
1570 exclude_paths = [
1571 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291572 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041573 ]
1574
dchenge07de812016-06-20 19:27:171575 # Dictionary mapping an OWNERS file path to Patterns.
1576 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1577 # rules ) to a PatternEntry.
1578 # PatternEntry is a dictionary with two keys:
1579 # - 'files': the files that are matched by this pattern
1580 # - 'rules': the per-file rules needed for this pattern
1581 # For example, if we expect OWNERS file to contain rules for *.mojom and
1582 # *_struct_traits*.*, Patterns might look like this:
1583 # {
1584 # '*.mojom': {
1585 # 'files': ...,
1586 # 'rules': [
1587 # 'per-file *.mojom=set noparent',
1588 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1589 # ],
1590 # },
1591 # '*_struct_traits*.*': {
1592 # 'files': ...,
1593 # 'rules': [
1594 # 'per-file *_struct_traits*.*=set noparent',
1595 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1596 # ],
1597 # },
1598 # }
1599 to_check = {}
1600
Daniel Cheng13ca61a882017-08-25 15:11:251601 def AddPatternToCheck(input_file, pattern):
1602 owners_file = input_api.os_path.join(
1603 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1604 if owners_file not in to_check:
1605 to_check[owners_file] = {}
1606 if pattern not in to_check[owners_file]:
1607 to_check[owners_file][pattern] = {
1608 'files': [],
1609 'rules': [
1610 'per-file %s=set noparent' % pattern,
1611 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1612 ]
1613 }
1614 to_check[owners_file][pattern]['files'].append(f)
1615
dchenge07de812016-06-20 19:27:171616 # Iterate through the affected files to see what we actually need to check
1617 # for. We should only nag patch authors about per-file rules if a file in that
1618 # directory would match that pattern. If a directory only contains *.mojom
1619 # files and no *_messages*.h files, we should only nag about rules for
1620 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251621 for f in input_api.AffectedFiles(include_deletes=False):
1622 # Manifest files don't have a strong naming convention. Instead, scan
1623 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161624 if (f.LocalPath().endswith('.json') and
1625 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1626 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251627 json_comment_eater = _ImportJSONCommentEater(input_api)
1628 mostly_json_lines = '\n'.join(f.NewContents())
1629 # Comments aren't allowed in strict JSON, so filter them out.
1630 json_lines = json_comment_eater.Nom(mostly_json_lines)
1631 json_content = input_api.json.loads(json_lines)
1632 if 'interface_provider_specs' in json_content:
1633 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171634 for pattern in file_patterns:
1635 if input_api.fnmatch.fnmatch(
1636 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041637 skip = False
1638 for exclude in exclude_paths:
1639 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1640 skip = True
1641 break
1642 if skip:
1643 continue
Daniel Cheng13ca61a882017-08-25 15:11:251644 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171645 break
1646
Daniel Cheng7052cdf2017-11-21 19:23:291647 return to_check
1648
1649
1650def _CheckIpcOwners(input_api, output_api):
1651 """Checks that affected files involving IPC have an IPC OWNERS rule."""
1652 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
1653
1654 if to_check:
1655 # If there are any OWNERS files to check, there are IPC-related changes in
1656 # this CL. Auto-CC the review list.
1657 output_api.AppendCC('[email protected]')
1658
1659 # Go through the OWNERS files to check, filtering out rules that are already
1660 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:171661 for owners_file, patterns in to_check.iteritems():
1662 try:
1663 with file(owners_file) as f:
1664 lines = set(f.read().splitlines())
1665 for entry in patterns.itervalues():
1666 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1667 ]
1668 except IOError:
1669 # No OWNERS file, so all the rules are definitely missing.
1670 continue
1671
1672 # All the remaining lines weren't found in OWNERS files, so emit an error.
1673 errors = []
1674 for owners_file, patterns in to_check.iteritems():
1675 missing_lines = []
1676 files = []
1677 for pattern, entry in patterns.iteritems():
1678 missing_lines.extend(entry['rules'])
1679 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1680 if missing_lines:
1681 errors.append(
Daniel Cheng52111692017-06-14 08:00:591682 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171683 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1684
1685 results = []
1686 if errors:
vabrf5ce3bf92016-07-11 14:52:411687 if input_api.is_committing:
1688 output = output_api.PresubmitError
1689 else:
1690 output = output_api.PresubmitPromptWarning
1691 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591692 'Found OWNERS files that need to be updated for IPC security ' +
1693 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171694 long_text='\n\n'.join(errors)))
1695
1696 return results
1697
1698
jbriance9e12f162016-11-25 07:57:501699def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311700 """Checks that added or removed lines in non third party affected
1701 header files do not lead to new useless class or struct forward
1702 declaration.
jbriance9e12f162016-11-25 07:57:501703 """
1704 results = []
1705 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1706 input_api.re.MULTILINE)
1707 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1708 input_api.re.MULTILINE)
1709 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311710 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191711 not f.LocalPath().startswith('third_party/blink') and
1712 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311713 not f.LocalPath().startswith('third_party/WebKit') and
1714 not f.LocalPath().startswith('third_party\\WebKit')):
1715 continue
1716
jbriance9e12f162016-11-25 07:57:501717 if not f.LocalPath().endswith('.h'):
1718 continue
1719
1720 contents = input_api.ReadFile(f)
1721 fwd_decls = input_api.re.findall(class_pattern, contents)
1722 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1723
1724 useless_fwd_decls = []
1725 for decl in fwd_decls:
1726 count = sum(1 for _ in input_api.re.finditer(
1727 r'\b%s\b' % input_api.re.escape(decl), contents))
1728 if count == 1:
1729 useless_fwd_decls.append(decl)
1730
1731 if not useless_fwd_decls:
1732 continue
1733
1734 for line in f.GenerateScmDiff().splitlines():
1735 if (line.startswith('-') and not line.startswith('--') or
1736 line.startswith('+') and not line.startswith('++')):
1737 for decl in useless_fwd_decls:
1738 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1739 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241740 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501741 (f.LocalPath(), decl)))
1742 useless_fwd_decls.remove(decl)
1743
1744 return results
1745
1746
dskiba88634f4e2015-08-14 23:03:291747def _CheckAndroidToastUsage(input_api, output_api):
1748 """Checks that code uses org.chromium.ui.widget.Toast instead of
1749 android.widget.Toast (Chromium Toast doesn't force hardware
1750 acceleration on low-end devices, saving memory).
1751 """
1752 toast_import_pattern = input_api.re.compile(
1753 r'^import android\.widget\.Toast;$')
1754
1755 errors = []
1756
1757 sources = lambda affected_file: input_api.FilterSourceFile(
1758 affected_file,
1759 black_list=(_EXCLUDED_PATHS +
1760 _TEST_CODE_EXCLUDED_PATHS +
1761 input_api.DEFAULT_BLACK_LIST +
1762 (r'^chromecast[\\\/].*',
1763 r'^remoting[\\\/].*')),
1764 white_list=(r'.*\.java$',))
1765
1766 for f in input_api.AffectedSourceFiles(sources):
1767 for line_num, line in f.ChangedContents():
1768 if toast_import_pattern.search(line):
1769 errors.append("%s:%d" % (f.LocalPath(), line_num))
1770
1771 results = []
1772
1773 if errors:
1774 results.append(output_api.PresubmitError(
1775 'android.widget.Toast usage is detected. Android toasts use hardware'
1776 ' acceleration, and can be\ncostly on low-end devices. Please use'
1777 ' org.chromium.ui.widget.Toast instead.\n'
1778 'Contact [email protected] if you have any questions.',
1779 errors))
1780
1781 return results
1782
1783
dgnaa68d5e2015-06-10 10:08:221784def _CheckAndroidCrLogUsage(input_api, output_api):
1785 """Checks that new logs using org.chromium.base.Log:
1786 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511787 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221788 """
pkotwicza1dd0b002016-05-16 14:41:041789
torne89540622017-03-24 19:41:301790 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041791 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301792 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041793 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301794 # WebView license viewer code cannot depend on //base; used in stub APK.
1795 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1796 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041797 ]
1798
dgnaa68d5e2015-06-10 10:08:221799 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121800 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1801 class_in_base_pattern = input_api.re.compile(
1802 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1803 has_some_log_import_pattern = input_api.re.compile(
1804 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221805 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121806 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221807 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511808 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221809 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221810
Vincent Scheib16d7b272015-09-15 18:09:071811 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221812 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041813 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1814 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121815
dgnaa68d5e2015-06-10 10:08:221816 tag_decl_errors = []
1817 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121818 tag_errors = []
dgn38736db2015-09-18 19:20:511819 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121820 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221821
1822 for f in input_api.AffectedSourceFiles(sources):
1823 file_content = input_api.ReadFile(f)
1824 has_modified_logs = False
1825
1826 # Per line checks
dgn87d9fb62015-06-12 09:15:121827 if (cr_log_import_pattern.search(file_content) or
1828 (class_in_base_pattern.search(file_content) and
1829 not has_some_log_import_pattern.search(file_content))):
1830 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221831 for line_num, line in f.ChangedContents():
1832
1833 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121834 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221835 if match:
1836 has_modified_logs = True
1837
1838 # Make sure it uses "TAG"
1839 if not match.group('tag') == 'TAG':
1840 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121841 else:
1842 # Report non cr Log function calls in changed lines
1843 for line_num, line in f.ChangedContents():
1844 if log_call_pattern.search(line):
1845 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221846
1847 # Per file checks
1848 if has_modified_logs:
1849 # Make sure the tag is using the "cr" prefix and is not too long
1850 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511851 tag_name = match.group('name') if match else None
1852 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221853 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511854 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221855 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511856 elif '.' in tag_name:
1857 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221858
1859 results = []
1860 if tag_decl_errors:
1861 results.append(output_api.PresubmitPromptWarning(
1862 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511863 '"private static final String TAG = "<package tag>".\n'
1864 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221865 tag_decl_errors))
1866
1867 if tag_length_errors:
1868 results.append(output_api.PresubmitError(
1869 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511870 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221871 tag_length_errors))
1872
1873 if tag_errors:
1874 results.append(output_api.PresubmitPromptWarning(
1875 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1876 tag_errors))
1877
dgn87d9fb62015-06-12 09:15:121878 if util_log_errors:
dgn4401aa52015-04-29 16:26:171879 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121880 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1881 util_log_errors))
1882
dgn38736db2015-09-18 19:20:511883 if tag_with_dot_errors:
1884 results.append(output_api.PresubmitPromptWarning(
1885 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1886 tag_with_dot_errors))
1887
dgn4401aa52015-04-29 16:26:171888 return results
1889
1890
Yoland Yanb92fa522017-08-28 17:37:061891def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1892 """Checks that junit.framework.* is no longer used."""
1893 deprecated_junit_framework_pattern = input_api.re.compile(
1894 r'^import junit\.framework\..*;',
1895 input_api.re.MULTILINE)
1896 sources = lambda x: input_api.FilterSourceFile(
1897 x, white_list=(r'.*\.java$',), black_list=None)
1898 errors = []
1899 for f in input_api.AffectedFiles(sources):
1900 for line_num, line in f.ChangedContents():
1901 if deprecated_junit_framework_pattern.search(line):
1902 errors.append("%s:%d" % (f.LocalPath(), line_num))
1903
1904 results = []
1905 if errors:
1906 results.append(output_api.PresubmitError(
1907 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1908 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1909 ' if you have any question.', errors))
1910 return results
1911
1912
1913def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1914 """Checks that if new Java test classes have inheritance.
1915 Either the new test class is JUnit3 test or it is a JUnit4 test class
1916 with a base class, either case is undesirable.
1917 """
1918 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1919
1920 sources = lambda x: input_api.FilterSourceFile(
1921 x, white_list=(r'.*Test\.java$',), black_list=None)
1922 errors = []
1923 for f in input_api.AffectedFiles(sources):
1924 if not f.OldContents():
1925 class_declaration_start_flag = False
1926 for line_num, line in f.ChangedContents():
1927 if class_declaration_pattern.search(line):
1928 class_declaration_start_flag = True
1929 if class_declaration_start_flag and ' extends ' in line:
1930 errors.append('%s:%d' % (f.LocalPath(), line_num))
1931 if '{' in line:
1932 class_declaration_start_flag = False
1933
1934 results = []
1935 if errors:
1936 results.append(output_api.PresubmitPromptWarning(
1937 'The newly created files include Test classes that inherits from base'
1938 ' class. Please do not use inheritance in JUnit4 tests or add new'
1939 ' JUnit3 tests. Contact [email protected] if you have any'
1940 ' questions.', errors))
1941 return results
1942
yolandyan45001472016-12-21 21:12:421943def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1944 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1945 deprecated_annotation_import_pattern = input_api.re.compile(
1946 r'^import android\.test\.suitebuilder\.annotation\..*;',
1947 input_api.re.MULTILINE)
1948 sources = lambda x: input_api.FilterSourceFile(
1949 x, white_list=(r'.*\.java$',), black_list=None)
1950 errors = []
1951 for f in input_api.AffectedFiles(sources):
1952 for line_num, line in f.ChangedContents():
1953 if deprecated_annotation_import_pattern.search(line):
1954 errors.append("%s:%d" % (f.LocalPath(), line_num))
1955
1956 results = []
1957 if errors:
1958 results.append(output_api.PresubmitError(
1959 'Annotations in android.test.suitebuilder.annotation have been'
1960 ' deprecated since API level 24. Please use android.support.test.filters'
1961 ' from //third_party/android_support_test_runner:runner_java instead.'
1962 ' Contact [email protected] if you have any questions.', errors))
1963 return results
1964
1965
agrieve7b6479d82015-10-07 14:24:221966def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1967 """Checks if MDPI assets are placed in a correct directory."""
1968 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1969 ('/res/drawable/' in f.LocalPath() or
1970 '/res/drawable-ldrtl/' in f.LocalPath()))
1971 errors = []
1972 for f in input_api.AffectedFiles(include_deletes=False,
1973 file_filter=file_filter):
1974 errors.append(' %s' % f.LocalPath())
1975
1976 results = []
1977 if errors:
1978 results.append(output_api.PresubmitError(
1979 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1980 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1981 '/res/drawable-ldrtl/.\n'
1982 'Contact [email protected] if you have questions.', errors))
1983 return results
1984
1985
Nate Fischer535972b2017-09-16 01:06:181986def _CheckAndroidWebkitImports(input_api, output_api):
1987 """Checks that code uses org.chromium.base.Callback instead of
1988 android.widget.ValueCallback except in the WebView glue layer.
1989 """
1990 valuecallback_import_pattern = input_api.re.compile(
1991 r'^import android\.webkit\.ValueCallback;$')
1992
1993 errors = []
1994
1995 sources = lambda affected_file: input_api.FilterSourceFile(
1996 affected_file,
1997 black_list=(_EXCLUDED_PATHS +
1998 _TEST_CODE_EXCLUDED_PATHS +
1999 input_api.DEFAULT_BLACK_LIST +
2000 (r'^android_webview[\\\/]glue[\\\/].*',)),
2001 white_list=(r'.*\.java$',))
2002
2003 for f in input_api.AffectedSourceFiles(sources):
2004 for line_num, line in f.ChangedContents():
2005 if valuecallback_import_pattern.search(line):
2006 errors.append("%s:%d" % (f.LocalPath(), line_num))
2007
2008 results = []
2009
2010 if errors:
2011 results.append(output_api.PresubmitError(
2012 'android.webkit.ValueCallback usage is detected outside of the glue'
2013 ' layer. To stay compatible with the support library, android.webkit.*'
2014 ' classes should only be used inside the glue layer and'
2015 ' org.chromium.base.Callback should be used instead.',
2016 errors))
2017
2018 return results
2019
2020
agrievef32bcc72016-04-04 14:57:402021class PydepsChecker(object):
2022 def __init__(self, input_api, pydeps_files):
2023 self._file_cache = {}
2024 self._input_api = input_api
2025 self._pydeps_files = pydeps_files
2026
2027 def _LoadFile(self, path):
2028 """Returns the list of paths within a .pydeps file relative to //."""
2029 if path not in self._file_cache:
2030 with open(path) as f:
2031 self._file_cache[path] = f.read()
2032 return self._file_cache[path]
2033
2034 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
2035 """Returns an interable of paths within the .pydep, relativized to //."""
2036 os_path = self._input_api.os_path
2037 pydeps_dir = os_path.dirname(pydeps_path)
2038 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2039 if not l.startswith('*'))
2040 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2041
2042 def _CreateFilesToPydepsMap(self):
2043 """Returns a map of local_path -> list_of_pydeps."""
2044 ret = {}
2045 for pydep_local_path in self._pydeps_files:
2046 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2047 ret.setdefault(path, []).append(pydep_local_path)
2048 return ret
2049
2050 def ComputeAffectedPydeps(self):
2051 """Returns an iterable of .pydeps files that might need regenerating."""
2052 affected_pydeps = set()
2053 file_to_pydeps_map = None
2054 for f in self._input_api.AffectedFiles(include_deletes=True):
2055 local_path = f.LocalPath()
2056 if local_path == 'DEPS':
2057 return self._pydeps_files
2058 elif local_path.endswith('.pydeps'):
2059 if local_path in self._pydeps_files:
2060 affected_pydeps.add(local_path)
2061 elif local_path.endswith('.py'):
2062 if file_to_pydeps_map is None:
2063 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2064 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2065 return affected_pydeps
2066
2067 def DetermineIfStale(self, pydeps_path):
2068 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412069 import difflib
agrievef32bcc72016-04-04 14:57:402070 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2071 cmd = old_pydeps_data[1][1:].strip()
John Budorick537d74d2018-01-23 18:43:212072 env = {
2073 'PYTHONDONTWRITEBYTECODE': '1'
2074 }
agrievef32bcc72016-04-04 14:57:402075 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick537d74d2018-01-23 18:43:212076 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412077 old_contents = old_pydeps_data[2:]
2078 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402079 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412080 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402081
2082
2083def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2084 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:402085 # This check is for Python dependency lists (.pydeps files), and involves
2086 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
2087 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:282088 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002089 return []
Mostyn Bramley-Moore6b427322017-12-21 22:11:022090 # TODO(agrieve): Update when there's a better way to detect
2091 # this: crbug.com/570091
agrievef32bcc72016-04-04 14:57:402092 is_android = input_api.os_path.exists('third_party/android_tools')
2093 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2094 results = []
2095 # First, check for new / deleted .pydeps.
2096 for f in input_api.AffectedFiles(include_deletes=True):
2097 if f.LocalPath().endswith('.pydeps'):
2098 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2099 results.append(output_api.PresubmitError(
2100 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2101 'remove %s' % f.LocalPath()))
2102 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2103 results.append(output_api.PresubmitError(
2104 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2105 'include %s' % f.LocalPath()))
2106
2107 if results:
2108 return results
2109
2110 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2111
2112 for pydep_path in checker.ComputeAffectedPydeps():
2113 try:
phajdan.jr0d9878552016-11-04 10:49:412114 result = checker.DetermineIfStale(pydep_path)
2115 if result:
2116 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402117 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412118 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2119 'To regenerate, run:\n\n %s' %
2120 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402121 except input_api.subprocess.CalledProcessError as error:
2122 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2123 long_text=error.output)]
2124
2125 return results
2126
2127
glidere61efad2015-02-18 17:39:432128def _CheckSingletonInHeaders(input_api, output_api):
2129 """Checks to make sure no header files have |Singleton<|."""
2130 def FileFilter(affected_file):
2131 # It's ok for base/memory/singleton.h to have |Singleton<|.
2132 black_list = (_EXCLUDED_PATHS +
2133 input_api.DEFAULT_BLACK_LIST +
2134 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2135 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2136
sergeyu34d21222015-09-16 00:11:442137 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432138 files = []
2139 for f in input_api.AffectedSourceFiles(FileFilter):
2140 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2141 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2142 contents = input_api.ReadFile(f)
2143 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242144 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432145 pattern.search(line)):
2146 files.append(f)
2147 break
2148
2149 if files:
yolandyandaabc6d2016-04-18 18:29:392150 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442151 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432152 'Please move them to an appropriate source file so that the ' +
2153 'template gets instantiated in a single compilation unit.',
2154 files) ]
2155 return []
2156
2157
[email protected]fd20b902014-05-09 02:14:532158_DEPRECATED_CSS = [
2159 # Values
2160 ( "-webkit-box", "flex" ),
2161 ( "-webkit-inline-box", "inline-flex" ),
2162 ( "-webkit-flex", "flex" ),
2163 ( "-webkit-inline-flex", "inline-flex" ),
2164 ( "-webkit-min-content", "min-content" ),
2165 ( "-webkit-max-content", "max-content" ),
2166
2167 # Properties
2168 ( "-webkit-background-clip", "background-clip" ),
2169 ( "-webkit-background-origin", "background-origin" ),
2170 ( "-webkit-background-size", "background-size" ),
2171 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442172 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532173
2174 # Functions
2175 ( "-webkit-gradient", "gradient" ),
2176 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2177 ( "-webkit-linear-gradient", "linear-gradient" ),
2178 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2179 ( "-webkit-radial-gradient", "radial-gradient" ),
2180 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2181]
2182
dbeam1ec68ac2016-12-15 05:22:242183def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532184 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252185 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342186 documentation and iOS CSS for dom distiller
2187 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252188 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532189 results = []
dbeam070cfe62014-10-22 06:44:022190 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252191 black_list = (_EXCLUDED_PATHS +
2192 _TEST_CODE_EXCLUDED_PATHS +
2193 input_api.DEFAULT_BLACK_LIST +
2194 (r"^chrome/common/extensions/docs",
2195 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342196 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442197 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252198 r"^native_client_sdk"))
2199 file_filter = lambda f: input_api.FilterSourceFile(
2200 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532201 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2202 for line_num, line in fpath.ChangedContents():
2203 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022204 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532205 results.append(output_api.PresubmitError(
2206 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2207 (fpath.LocalPath(), line_num, deprecated_value, value)))
2208 return results
2209
mohan.reddyf21db962014-10-16 12:26:472210
dbeam070cfe62014-10-22 06:44:022211_DEPRECATED_JS = [
2212 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2213 ( "__defineGetter__", "Object.defineProperty" ),
2214 ( "__defineSetter__", "Object.defineProperty" ),
2215]
2216
dbeam1ec68ac2016-12-15 05:22:242217def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022218 """Make sure that we don't use deprecated JS in Chrome code."""
2219 results = []
2220 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2221 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2222 input_api.DEFAULT_BLACK_LIST)
2223 file_filter = lambda f: input_api.FilterSourceFile(
2224 f, white_list=file_inclusion_pattern, black_list=black_list)
2225 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2226 for lnum, line in fpath.ChangedContents():
2227 for (deprecated, replacement) in _DEPRECATED_JS:
2228 if deprecated in line:
2229 results.append(output_api.PresubmitError(
2230 "%s:%d: Use of deprecated JS %s, use %s instead" %
2231 (fpath.LocalPath(), lnum, deprecated, replacement)))
2232 return results
2233
dpapadd651231d82017-07-21 02:44:472234def _CheckForRiskyJsArrowFunction(line_number, line):
2235 if ' => ' in line:
2236 return "line %d, is using an => (arrow) function\n %s\n" % (
2237 line_number, line)
2238 return ''
2239
2240def _CheckForRiskyJsConstLet(input_api, line_number, line):
2241 if input_api.re.match('^\s*(const|let)\s', line):
2242 return "line %d, is using const/let keyword\n %s\n" % (
2243 line_number, line)
2244 return ''
dbeam070cfe62014-10-22 06:44:022245
dbeam1ec68ac2016-12-15 05:22:242246def _CheckForRiskyJsFeatures(input_api, output_api):
2247 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002248 # 'ui/webui/resources/cr_components are not allowed on ios'
2249 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572250 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002251 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472252 results = []
dbeam1ec68ac2016-12-15 05:22:242253 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472254 arrow_error_lines = []
2255 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242256 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472257 arrow_error_lines += filter(None, [
2258 _CheckForRiskyJsArrowFunction(lnum, line),
2259 ])
dbeam1ec68ac2016-12-15 05:22:242260
dpapadd651231d82017-07-21 02:44:472261 const_let_error_lines += filter(None, [
2262 _CheckForRiskyJsConstLet(input_api, lnum, line),
2263 ])
dbeam1ec68ac2016-12-15 05:22:242264
dpapadd651231d82017-07-21 02:44:472265 if arrow_error_lines:
2266 arrow_error_lines = map(
2267 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2268 results.append(
2269 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2270"""
2271Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242272%s
2273Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2274https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472275""" % f.LocalPath()
2276 ])))
dbeam1ec68ac2016-12-15 05:22:242277
dpapadd651231d82017-07-21 02:44:472278 if const_let_error_lines:
2279 const_let_error_lines = map(
2280 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2281 results.append(
2282 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2283"""
2284Use of const/let keywords detected in:
2285%s
2286Please ensure your code does not run on iOS9 because const/let is not fully
2287supported.
2288https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2289https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2290""" % f.LocalPath()
2291 ])))
2292
2293 return results
dbeam1ec68ac2016-12-15 05:22:242294
rlanday6802cf632017-05-30 17:48:362295def _CheckForRelativeIncludes(input_api, output_api):
2296 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2297 import sys
2298 original_sys_path = sys.path
2299 try:
2300 sys.path = sys.path + [input_api.os_path.join(
2301 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2302 from cpp_checker import CppChecker
2303 finally:
2304 # Restore sys.path to what it was before.
2305 sys.path = original_sys_path
2306
2307 bad_files = {}
2308 for f in input_api.AffectedFiles(include_deletes=False):
2309 if (f.LocalPath().startswith('third_party') and
2310 not f.LocalPath().startswith('third_party/WebKit') and
2311 not f.LocalPath().startswith('third_party\\WebKit')):
2312 continue
2313
2314 if not CppChecker.IsCppFile(f.LocalPath()):
2315 continue
2316
2317 relative_includes = [line for line_num, line in f.ChangedContents()
2318 if "#include" in line and "../" in line]
2319 if not relative_includes:
2320 continue
2321 bad_files[f.LocalPath()] = relative_includes
2322
2323 if not bad_files:
2324 return []
2325
2326 error_descriptions = []
2327 for file_path, bad_lines in bad_files.iteritems():
2328 error_description = file_path
2329 for line in bad_lines:
2330 error_description += '\n ' + line
2331 error_descriptions.append(error_description)
2332
2333 results = []
2334 results.append(output_api.PresubmitError(
2335 'You added one or more relative #include paths (including "../").\n'
2336 'These shouldn\'t be used because they can be used to include headers\n'
2337 'from code that\'s not correctly specified as a dependency in the\n'
2338 'relevant BUILD.gn file(s).',
2339 error_descriptions))
2340
2341 return results
2342
Takeshi Yoshinoe387aa32017-08-02 13:16:132343
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202344def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2345 if not isinstance(key, ast.Str):
2346 return 'Key at line %d must be a string literal' % key.lineno
2347 if not isinstance(value, ast.Dict):
2348 return 'Value at line %d must be a dict' % value.lineno
2349 if len(value.keys) != 1:
2350 return 'Dict at line %d must have single entry' % value.lineno
2351 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2352 return (
2353 'Entry at line %d must have a string literal \'filepath\' as key' %
2354 value.lineno)
2355 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132356
Takeshi Yoshinoe387aa32017-08-02 13:16:132357
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202358def _CheckWatchlistsEntrySyntax(key, value, ast):
2359 if not isinstance(key, ast.Str):
2360 return 'Key at line %d must be a string literal' % key.lineno
2361 if not isinstance(value, ast.List):
2362 return 'Value at line %d must be a list' % value.lineno
2363 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132364
Takeshi Yoshinoe387aa32017-08-02 13:16:132365
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202366def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2367 mismatch_template = (
2368 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2369 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132370
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202371 i = 0
2372 last_key = ''
2373 while True:
2374 if i >= len(wd_dict.keys):
2375 if i >= len(w_dict.keys):
2376 return None
2377 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2378 elif i >= len(w_dict.keys):
2379 return (
2380 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132381
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202382 wd_key = wd_dict.keys[i]
2383 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132384
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202385 result = _CheckWatchlistDefinitionsEntrySyntax(
2386 wd_key, wd_dict.values[i], ast)
2387 if result is not None:
2388 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132389
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202390 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2391 if result is not None:
2392 return 'Bad entry in WATCHLISTS dict: %s' % result
2393
2394 if wd_key.s != w_key.s:
2395 return mismatch_template % (
2396 '%s at line %d' % (wd_key.s, wd_key.lineno),
2397 '%s at line %d' % (w_key.s, w_key.lineno))
2398
2399 if wd_key.s < last_key:
2400 return (
2401 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2402 (wd_key.lineno, w_key.lineno))
2403 last_key = wd_key.s
2404
2405 i = i + 1
2406
2407
2408def _CheckWATCHLISTSSyntax(expression, ast):
2409 if not isinstance(expression, ast.Expression):
2410 return 'WATCHLISTS file must contain a valid expression'
2411 dictionary = expression.body
2412 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2413 return 'WATCHLISTS file must have single dict with exactly two entries'
2414
2415 first_key = dictionary.keys[0]
2416 first_value = dictionary.values[0]
2417 second_key = dictionary.keys[1]
2418 second_value = dictionary.values[1]
2419
2420 if (not isinstance(first_key, ast.Str) or
2421 first_key.s != 'WATCHLIST_DEFINITIONS' or
2422 not isinstance(first_value, ast.Dict)):
2423 return (
2424 'The first entry of the dict in WATCHLISTS file must be '
2425 'WATCHLIST_DEFINITIONS dict')
2426
2427 if (not isinstance(second_key, ast.Str) or
2428 second_key.s != 'WATCHLISTS' or
2429 not isinstance(second_value, ast.Dict)):
2430 return (
2431 'The second entry of the dict in WATCHLISTS file must be '
2432 'WATCHLISTS dict')
2433
2434 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132435
2436
2437def _CheckWATCHLISTS(input_api, output_api):
2438 for f in input_api.AffectedFiles(include_deletes=False):
2439 if f.LocalPath() == 'WATCHLISTS':
2440 contents = input_api.ReadFile(f, 'r')
2441
2442 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202443 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132444 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202445 # Get an AST tree for it and scan the tree for detailed style checking.
2446 expression = input_api.ast.parse(
2447 contents, filename='WATCHLISTS', mode='eval')
2448 except ValueError as e:
2449 return [output_api.PresubmitError(
2450 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2451 except SyntaxError as e:
2452 return [output_api.PresubmitError(
2453 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2454 except TypeError as e:
2455 return [output_api.PresubmitError(
2456 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132457
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202458 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2459 if result is not None:
2460 return [output_api.PresubmitError(result)]
2461 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132462
2463 return []
2464
2465
dgnaa68d5e2015-06-10 10:08:222466def _AndroidSpecificOnUploadChecks(input_api, output_api):
2467 """Groups checks that target android code."""
2468 results = []
dgnaa68d5e2015-06-10 10:08:222469 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222470 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292471 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062472 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2473 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422474 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182475 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222476 return results
2477
2478
[email protected]22c9bd72011-03-27 16:47:392479def _CommonChecks(input_api, output_api):
2480 """Checks common to both upload and commit."""
2481 results = []
2482 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382483 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542484 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:082485
2486 author = input_api.change.author_email
2487 if author and author not in _KNOWN_ROBOTS:
2488 results.extend(
2489 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
2490
[email protected]55459852011-08-10 15:17:192491 results.extend(
[email protected]760deea2013-12-10 19:33:492492 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542493 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182494 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522495 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222496 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442497 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592498 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062499 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122500 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182501 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222502 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302503 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492504 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032505 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492506 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442507 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272508 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072509 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542510 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442511 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392512 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552513 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042514 results.extend(
2515 input_api.canned_checks.CheckChangeHasNoTabs(
2516 input_api,
2517 output_api,
2518 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402519 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162520 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082521 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242522 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2523 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472524 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042525 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232526 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432527 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402528 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152529 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172530 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502531 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242532 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362533 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132534 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432535 results.extend(input_api.RunTests(
2536 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242537
2538 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2539 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2540 input_api, output_api,
2541 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382542 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392543 return results
[email protected]1f7b4172010-01-28 01:17:342544
[email protected]b337cb5b2011-01-23 21:24:052545
[email protected]b8079ae4a2012-12-05 19:56:492546def _CheckPatchFiles(input_api, output_api):
2547 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2548 if f.LocalPath().endswith(('.orig', '.rej'))]
2549 if problems:
2550 return [output_api.PresubmitError(
2551 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032552 else:
2553 return []
[email protected]b8079ae4a2012-12-05 19:56:492554
2555
Kent Tamura5a8755d2017-06-29 23:37:072556def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212557 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2558 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2559 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072560 include_re = input_api.re.compile(
2561 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2562 extension_re = input_api.re.compile(r'\.[a-z]+$')
2563 errors = []
2564 for f in input_api.AffectedFiles():
2565 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2566 continue
2567 found_line_number = None
2568 found_macro = None
2569 for line_num, line in f.ChangedContents():
2570 match = macro_re.search(line)
2571 if match:
2572 found_line_number = line_num
2573 found_macro = match.group(2)
2574 break
2575 if not found_line_number:
2576 continue
2577
2578 found_include = False
2579 for line in f.NewContents():
2580 if include_re.search(line):
2581 found_include = True
2582 break
2583 if found_include:
2584 continue
2585
2586 if not f.LocalPath().endswith('.h'):
2587 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2588 try:
2589 content = input_api.ReadFile(primary_header_path, 'r')
2590 if include_re.search(content):
2591 continue
2592 except IOError:
2593 pass
2594 errors.append('%s:%d %s macro is used without including build/'
2595 'build_config.h.'
2596 % (f.LocalPath(), found_line_number, found_macro))
2597 if errors:
2598 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2599 return []
2600
2601
[email protected]b00342e7f2013-03-26 16:21:542602def _DidYouMeanOSMacro(bad_macro):
2603 try:
2604 return {'A': 'OS_ANDROID',
2605 'B': 'OS_BSD',
2606 'C': 'OS_CHROMEOS',
2607 'F': 'OS_FREEBSD',
2608 'L': 'OS_LINUX',
2609 'M': 'OS_MACOSX',
2610 'N': 'OS_NACL',
2611 'O': 'OS_OPENBSD',
2612 'P': 'OS_POSIX',
2613 'S': 'OS_SOLARIS',
2614 'W': 'OS_WIN'}[bad_macro[3].upper()]
2615 except KeyError:
2616 return ''
2617
2618
2619def _CheckForInvalidOSMacrosInFile(input_api, f):
2620 """Check for sensible looking, totally invalid OS macros."""
2621 preprocessor_statement = input_api.re.compile(r'^\s*#')
2622 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2623 results = []
2624 for lnum, line in f.ChangedContents():
2625 if preprocessor_statement.search(line):
2626 for match in os_macro.finditer(line):
2627 if not match.group(1) in _VALID_OS_MACROS:
2628 good = _DidYouMeanOSMacro(match.group(1))
2629 did_you_mean = ' (did you mean %s?)' % good if good else ''
2630 results.append(' %s:%d %s%s' % (f.LocalPath(),
2631 lnum,
2632 match.group(1),
2633 did_you_mean))
2634 return results
2635
2636
2637def _CheckForInvalidOSMacros(input_api, output_api):
2638 """Check all affected files for invalid OS macros."""
2639 bad_macros = []
2640 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472641 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542642 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2643
2644 if not bad_macros:
2645 return []
2646
2647 return [output_api.PresubmitError(
2648 'Possibly invalid OS macro[s] found. Please fix your code\n'
2649 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2650
lliabraa35bab3932014-10-01 12:16:442651
2652def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2653 """Check all affected files for invalid "if defined" macros."""
2654 ALWAYS_DEFINED_MACROS = (
2655 "TARGET_CPU_PPC",
2656 "TARGET_CPU_PPC64",
2657 "TARGET_CPU_68K",
2658 "TARGET_CPU_X86",
2659 "TARGET_CPU_ARM",
2660 "TARGET_CPU_MIPS",
2661 "TARGET_CPU_SPARC",
2662 "TARGET_CPU_ALPHA",
2663 "TARGET_IPHONE_SIMULATOR",
2664 "TARGET_OS_EMBEDDED",
2665 "TARGET_OS_IPHONE",
2666 "TARGET_OS_MAC",
2667 "TARGET_OS_UNIX",
2668 "TARGET_OS_WIN32",
2669 )
2670 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2671 results = []
2672 for lnum, line in f.ChangedContents():
2673 for match in ifdef_macro.finditer(line):
2674 if match.group(1) in ALWAYS_DEFINED_MACROS:
2675 always_defined = ' %s is always defined. ' % match.group(1)
2676 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2677 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2678 lnum,
2679 always_defined,
2680 did_you_mean))
2681 return results
2682
2683
2684def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2685 """Check all affected files for invalid "if defined" macros."""
2686 bad_macros = []
2687 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212688 if f.LocalPath().startswith('third_party/sqlite/'):
2689 continue
lliabraa35bab3932014-10-01 12:16:442690 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2691 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2692
2693 if not bad_macros:
2694 return []
2695
2696 return [output_api.PresubmitError(
2697 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2698 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2699 bad_macros)]
2700
2701
mlamouria82272622014-09-16 18:45:042702def _CheckForIPCRules(input_api, output_api):
2703 """Check for same IPC rules described in
2704 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2705 """
2706 base_pattern = r'IPC_ENUM_TRAITS\('
2707 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2708 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2709
2710 problems = []
2711 for f in input_api.AffectedSourceFiles(None):
2712 local_path = f.LocalPath()
2713 if not local_path.endswith('.h'):
2714 continue
2715 for line_number, line in f.ChangedContents():
2716 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2717 problems.append(
2718 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2719
2720 if problems:
2721 return [output_api.PresubmitPromptWarning(
2722 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2723 else:
2724 return []
2725
[email protected]b00342e7f2013-03-26 16:21:542726
mostynbb639aca52015-01-07 20:31:232727def _CheckForWindowsLineEndings(input_api, output_api):
2728 """Check source code and known ascii text files for Windows style line
2729 endings.
2730 """
earthdok1b5e0ee2015-03-10 15:19:102731 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232732
2733 file_inclusion_pattern = (
2734 known_text_files,
2735 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2736 )
2737
mostynbb639aca52015-01-07 20:31:232738 problems = []
Andrew Grieve933d12e2017-10-30 20:22:532739 source_file_filter = lambda f: input_api.FilterSourceFile(
2740 f, white_list=file_inclusion_pattern, black_list=None)
2741 for f in input_api.AffectedSourceFiles(source_file_filter):
2742 for line_number, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:232743 if line.endswith('\r\n'):
Andrew Grieve933d12e2017-10-30 20:22:532744 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:232745
2746 if problems:
2747 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2748 'these files to contain Windows style line endings?\n' +
2749 '\n'.join(problems))]
2750
2751 return []
2752
2753
pastarmovj89f7ee12016-09-20 14:58:132754def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2755 lint_filters=None, verbose_level=None):
2756 """Checks that all source files use SYSLOG properly."""
2757 syslog_files = []
2758 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562759 for line_number, line in f.ChangedContents():
2760 if 'SYSLOG' in line:
2761 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2762
pastarmovj89f7ee12016-09-20 14:58:132763 if syslog_files:
2764 return [output_api.PresubmitPromptWarning(
2765 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2766 ' calls.\nFiles to check:\n', items=syslog_files)]
2767 return []
2768
2769
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192770def _CheckCrbugLinksHaveHttps(input_api, output_api):
Miguel Casas68bdb652017-12-19 16:29:092771 """Checks that crbug(.com) links are correctly prefixed by https://,
2772 unless they come in the accepted form TODO(crbug.com/...)
2773 """
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192774 white_list = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2775 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS)
2776 sources = lambda f: input_api.FilterSourceFile(
2777 f, white_list=white_list, black_list=black_list)
2778
2779 pattern = input_api.re.compile(r'//.*(?<!:\/\/)crbug[.com]*')
Miguel Casas68bdb652017-12-19 16:29:092780 accepted_pattern = input_api.re.compile(r'//.*TODO\(crbug[.com]*');
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192781 problems = []
2782 for f in input_api.AffectedSourceFiles(sources):
2783 for line_num, line in f.ChangedContents():
Miguel Casas68bdb652017-12-19 16:29:092784 if pattern.search(line) and not accepted_pattern.search(line):
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192785 problems.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2786
2787 if problems:
2788 return [output_api.PresubmitPromptWarning(
2789 'Found unprefixed crbug.com URL(s), consider prepending https://\n'+
2790 '\n'.join(problems))]
2791 return []
2792
2793
[email protected]1f7b4172010-01-28 01:17:342794def CheckChangeOnUpload(input_api, output_api):
2795 results = []
2796 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472797 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282798 results.extend(
jam93a6ee792017-02-08 23:59:222799 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192800 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222801 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132802 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162803 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192804 results.extend(_CheckCrbugLinksHaveHttps(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542805 return results
[email protected]ca8d1982009-02-19 16:33:122806
2807
[email protected]1bfb8322014-04-23 01:02:412808def GetTryServerMasterForBot(bot):
2809 """Returns the Try Server master for the given bot.
2810
[email protected]0bb112362014-07-26 04:38:322811 It tries to guess the master from the bot name, but may still fail
2812 and return None. There is no longer a default master.
2813 """
2814 # Potentially ambiguous bot names are listed explicitly.
2815 master_map = {
tandriie5587792016-07-14 00:34:502816 'chromium_presubmit': 'master.tryserver.chromium.linux',
2817 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412818 }
[email protected]0bb112362014-07-26 04:38:322819 master = master_map.get(bot)
2820 if not master:
wnwen4fbaab82016-05-25 12:54:362821 if 'android' in bot:
tandriie5587792016-07-14 00:34:502822 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362823 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502824 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322825 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502826 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322827 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502828 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322829 return master
[email protected]1bfb8322014-04-23 01:02:412830
2831
[email protected]ca8d1982009-02-19 16:33:122832def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542833 results = []
[email protected]1f7b4172010-01-28 01:17:342834 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542835 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272836 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342837 input_api,
2838 output_api,
[email protected]2fdd1f362013-01-16 03:56:032839 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272840
jam93a6ee792017-02-08 23:59:222841 results.extend(
2842 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542843 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2844 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412845 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2846 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542847 return results