blob: 199158e66538c27e2b82192dbdd7ab82c14b0eb9 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]40d1dbb2012-10-26 07:18:0013 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
14 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2815 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0816 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5417 r"^skia[\\\/].*",
Kent Tamurae9b3a9ec2017-08-31 02:20:1918 r"^third_party[\\\/](WebKit|blink)[\\\/].*",
Mark Mentovaiebb9ddd62017-09-25 17:24:4119 r"^third_party[\\\/]breakpad[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
vapierb2053f542017-03-09 19:46:1026 r"tools[\\\/]md_browser[\\\/].*\.css$",
Kenneth Russell077c8d92017-12-16 02:52:1427 # Test pages for Maps telemetry tests.
28 r"tools[\\\/]perf[\\\/]page_sets[\\\/]maps_perf_test.*",
ehmaldonado78eee2ed2017-03-28 13:16:5429 # Test pages for WebRTC telemetry tests.
30 r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4031)
[email protected]ca8d1982009-02-19 16:33:1232
wnwenbdc444e2016-05-25 13:44:1533
[email protected]06e6d0ff2012-12-11 01:36:4434# Fragment of a regular expression that matches C++ and Objective-C++
35# implementation files.
36_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
37
wnwenbdc444e2016-05-25 13:44:1538
[email protected]06e6d0ff2012-12-11 01:36:4439# Regular expression that matches code only used for test binaries
40# (best effort).
41_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4942 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4443 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
Steven Holte27008b7422018-01-29 20:55:4444 r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1245 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4446 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0548 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4949 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4750 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4951 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0852 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4953 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4454)
[email protected]ca8d1982009-02-19 16:33:1255
wnwenbdc444e2016-05-25 13:44:1556
[email protected]eea609a2011-11-18 13:10:1257_TEST_ONLY_WARNING = (
58 'You might be calling functions intended only for testing from\n'
59 'production code. It is OK to ignore this warning if you know what\n'
60 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5861 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1262
63
[email protected]cf9b78f2012-11-14 11:40:2864_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4065 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2166 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
67 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2868
wnwenbdc444e2016-05-25 13:44:1569
Eric Stevensona9a980972017-09-23 00:04:4170_BANNED_JAVA_FUNCTIONS = (
71 (
72 'StrictMode.allowThreadDiskReads()',
73 (
74 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
75 'directly.',
76 ),
77 False,
78 ),
79 (
80 'StrictMode.allowThreadDiskWrites()',
81 (
82 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
83 'directly.',
84 ),
85 False,
86 ),
87)
88
[email protected]127f18ec2012-06-16 05:05:5989_BANNED_OBJC_FUNCTIONS = (
90 (
91 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2092 (
93 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5994 'prohibited. Please use CrTrackingArea instead.',
95 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
96 ),
97 False,
98 ),
99 (
[email protected]eaae1972014-04-16 04:17:26100 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20101 (
102 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59103 'instead.',
104 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
105 ),
106 False,
107 ),
108 (
109 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20110 (
111 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59112 'Please use |convertPoint:(point) fromView:nil| instead.',
113 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
114 ),
115 True,
116 ),
117 (
118 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20119 (
120 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59121 'Please use |convertPoint:(point) toView:nil| instead.',
122 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
123 ),
124 True,
125 ),
126 (
127 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20128 (
129 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59130 'Please use |convertRect:(point) fromView:nil| instead.',
131 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
132 ),
133 True,
134 ),
135 (
136 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20137 (
138 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59139 'Please use |convertRect:(point) toView:nil| instead.',
140 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
141 ),
142 True,
143 ),
144 (
145 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20146 (
147 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59148 'Please use |convertSize:(point) fromView:nil| instead.',
149 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
150 ),
151 True,
152 ),
153 (
154 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20155 (
156 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59157 'Please use |convertSize:(point) toView:nil| instead.',
158 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
159 ),
160 True,
161 ),
jif65398702016-10-27 10:19:48162 (
163 r"/\s+UTF8String\s*]",
164 (
165 'The use of -[NSString UTF8String] is dangerous as it can return null',
166 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
167 'Please use |SysNSStringToUTF8| instead.',
168 ),
169 True,
170 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34171 (
172 r'__unsafe_unretained',
173 (
174 'The use of __unsafe_unretained is almost certainly wrong, unless',
175 'when interacting with NSFastEnumeration or NSInvocation.',
176 'Please use __weak in files build with ARC, nothing otherwise.',
177 ),
178 False,
179 ),
[email protected]127f18ec2012-06-16 05:05:59180)
181
Sylvain Defresnea8b73d252018-02-28 15:45:54182_BANNED_IOS_OBJC_FUNCTIONS = (
183 (
184 r'/\bTEST[(]',
185 (
186 'TEST() macro should not be used in Objective-C++ code as it does not ',
187 'drain the autorelease pool at the end of the test. Use TEST_F() ',
188 'macro instead with a fixture inheriting from PlatformTest (or a ',
189 'typedef).'
190 ),
191 True,
192 ),
193 (
194 r'/\btesting::Test\b',
195 (
196 'testing::Test should not be used in Objective-C++ code as it does ',
197 'not drain the autorelease pool at the end of the test. Use ',
198 'PlatformTest instead.'
199 ),
200 True,
201 ),
202)
203
[email protected]127f18ec2012-06-16 05:05:59204
205_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20206 # Make sure that gtest's FRIEND_TEST() macro is not used; the
207 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30208 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20209 (
thomasandersone7caaa9b2017-03-29 19:22:53210 r'\bNULL\b',
211 (
212 'New code should not use NULL. Use nullptr instead.',
213 ),
214 True,
215 (),
216 ),
217 (
[email protected]23e6cbc2012-06-16 18:51:20218 'FRIEND_TEST(',
219 (
[email protected]e3c945502012-06-26 20:01:49220 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20221 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
222 ),
223 False,
[email protected]7345da02012-11-27 14:31:49224 (),
[email protected]23e6cbc2012-06-16 18:51:20225 ),
226 (
thomasanderson4b569052016-09-14 20:15:53227 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
228 (
229 'Chrome clients wishing to select events on X windows should use',
230 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
231 'you are selecting events from the GPU process, or if you are using',
232 'an XDisplay other than gfx::GetXDisplay().',
233 ),
234 True,
235 (
236 r"^ui[\\\/]gl[\\\/].*\.cc$",
237 r"^media[\\\/]gpu[\\\/].*\.cc$",
238 r"^gpu[\\\/].*\.cc$",
239 ),
240 ),
241 (
thomasandersone043e3ce2017-06-08 00:43:20242 r'XInternAtom|xcb_intern_atom',
243 (
thomasanderson11aa41d2017-06-08 22:22:38244 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20245 ),
246 True,
247 (
thomasanderson11aa41d2017-06-08 22:22:38248 r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$",
249 r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20250 r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$",
251 ),
252 ),
253 (
tomhudsone2c14d552016-05-26 17:07:46254 'setMatrixClip',
255 (
256 'Overriding setMatrixClip() is prohibited; ',
257 'the base function is deprecated. ',
258 ),
259 True,
260 (),
261 ),
262 (
[email protected]52657f62013-05-20 05:30:31263 'SkRefPtr',
264 (
265 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22266 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31267 ),
268 True,
269 (),
270 ),
271 (
272 'SkAutoRef',
273 (
274 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22275 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31276 ),
277 True,
278 (),
279 ),
280 (
281 'SkAutoTUnref',
282 (
283 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22284 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31285 ),
286 True,
287 (),
288 ),
289 (
290 'SkAutoUnref',
291 (
292 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
293 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22294 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31295 ),
296 True,
297 (),
298 ),
[email protected]d89eec82013-12-03 14:10:59299 (
300 r'/HANDLE_EINTR\(.*close',
301 (
302 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
303 'descriptor will be closed, and it is incorrect to retry the close.',
304 'Either call close directly and ignore its return value, or wrap close',
305 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
306 ),
307 True,
308 (),
309 ),
310 (
311 r'/IGNORE_EINTR\((?!.*close)',
312 (
313 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
314 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
315 ),
316 True,
317 (
318 # Files that #define IGNORE_EINTR.
319 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
320 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
321 ),
322 ),
[email protected]ec5b3f02014-04-04 18:43:43323 (
324 r'/v8::Extension\(',
325 (
326 'Do not introduce new v8::Extensions into the code base, use',
327 'gin::Wrappable instead. See http://crbug.com/334679',
328 ),
329 True,
[email protected]f55c90ee62014-04-12 00:50:03330 (
joaodasilva718f87672014-08-30 09:25:49331 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03332 ),
[email protected]ec5b3f02014-04-04 18:43:43333 ),
skyostilf9469f72015-04-20 10:38:52334 (
jame2d1a952016-04-02 00:27:10335 '#pragma comment(lib,',
336 (
337 'Specify libraries to link with in build files and not in the source.',
338 ),
339 True,
340 (),
341 ),
fdorayc4ac18d2017-05-01 21:39:59342 (
gabd52c912a2017-05-11 04:15:59343 'base::SequenceChecker',
344 (
345 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
346 ),
347 False,
348 (),
349 ),
350 (
351 'base::ThreadChecker',
352 (
353 'Consider using THREAD_CHECKER macros instead of the class directly.',
354 ),
355 False,
356 (),
357 ),
dbeamb6f4fde2017-06-15 04:03:06358 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06359 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
360 (
361 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
362 'deprecated (http://crbug.com/634507). Please avoid converting away',
363 'from the Time types in Chromium code, especially if any math is',
364 'being done on time values. For interfacing with platform/library',
365 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
366 'type converter methods instead. For faking TimeXXX values (for unit',
367 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
368 'other use cases, please contact base/time/OWNERS.',
369 ),
370 False,
371 (),
372 ),
373 (
dbeamb6f4fde2017-06-15 04:03:06374 'CallJavascriptFunctionUnsafe',
375 (
376 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
377 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
378 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
379 ),
380 False,
381 (
382 r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$',
383 r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$',
384 r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$',
385 ),
386 ),
dskiba1474c2bfd62017-07-20 02:19:24387 (
388 'leveldb::DB::Open',
389 (
390 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
391 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
392 "Chrome's tracing, making their memory usage visible.",
393 ),
394 True,
395 (
396 r'^third_party/leveldatabase/.*\.(cc|h)$',
397 ),
Gabriel Charette0592c3a2017-07-26 12:02:04398 ),
399 (
Chris Mumfordc38afb62017-10-09 17:55:08400 'leveldb::NewMemEnv',
401 (
402 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
403 'third_party/leveldatabase/leveldb_chrome.h.',
404 ),
405 True,
406 (
407 r'^third_party/leveldatabase/.*\.(cc|h)$',
408 ),
409 ),
410 (
Gabriel Charetted9839bc2017-07-29 14:17:47411 'MessageLoop::QuitWhenIdleClosure',
Gabriel Charette0592c3a2017-07-26 12:02:04412 (
Peter Kasting9e7ccfa52018-02-06 00:01:20413 'MessageLoop::QuitWhenIdleClosure is deprecated. Please use a',
414 'QuitWhenIdleClosure obtained from a specific RunLoop instance.',
Gabriel Charette0592c3a2017-07-26 12:02:04415 ),
Peter Kasting9e7ccfa52018-02-06 00:01:20416 False,
Gabriel Charette0592c3a2017-07-26 12:02:04417 (),
Gabriel Charetted9839bc2017-07-29 14:17:47418 ),
419 (
420 'RunLoop::QuitCurrent',
421 (
Robert Liao64b7ab22017-08-04 23:03:43422 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
423 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47424 ),
425 True,
426 (),
Gabriel Charettea44975052017-08-21 23:14:04427 ),
428 (
429 'base::ScopedMockTimeMessageLoopTaskRunner',
430 (
431 'ScopedMockTimeMessageLoopTaskRunner is deprecated.',
432 ),
433 True,
434 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57435 ),
436 (
437 r'std::regex',
438 (
439 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02440 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57441 ),
442 True,
443 (),
Francois Doray43670e32017-09-27 12:40:38444 ),
445 (
446 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
447 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
448 (
449 'Use the new API in base/threading/thread_restrictions.h.',
450 ),
451 True,
452 (),
453 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38454 (
455 r'/\bbase::Bind\(',
456 (
Gabriel Charette147335ea2018-03-22 15:59:19457 'Please consider using base::Bind{Once,Repeating} instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02458 'of base::Bind. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38459 ),
460 False,
461 (),
462 ),
463 (
464 r'/\bbase::Callback<',
465 (
Gabriel Charette147335ea2018-03-22 15:59:19466 'Please consider using base::{Once,Repeating}Callback instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02467 'of base::Callback. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38468 ),
469 False,
470 (),
471 ),
472 (
473 r'/\bbase::Closure\b',
474 (
Gabriel Charette147335ea2018-03-22 15:59:19475 'Please consider using base::{Once,Repeating}Closure instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02476 'of base::Closure. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38477 ),
478 False,
479 (),
480 ),
Victor Costan3653df62018-02-08 21:38:16481 (
Gabriel Charette147335ea2018-03-22 15:59:19482 r'RunMessageLoop',
483 (
484 'RunMessageLoop is deprecated, use RunLoop instead.',
485 ),
486 False,
487 (),
488 ),
489 (
490 r'RunThisRunLoop',
491 (
492 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
493 ),
494 False,
495 (),
496 ),
497 (
498 r'RunAllPendingInMessageLoop()',
499 (
500 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
501 "if you're convinced you need this.",
502 ),
503 False,
504 (),
505 ),
506 (
507 r'RunAllPendingInMessageLoop(BrowserThread',
508 (
509 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
510 'BrowserThread::UI, TestBrowserThreadBundle::RunIOThreadUntilIdle',
511 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
512 'async events instead of flushing threads.',
513 ),
514 False,
515 (),
516 ),
517 (
518 r'MessageLoopRunner',
519 (
520 'MessageLoopRunner is deprecated, use RunLoop instead.',
521 ),
522 False,
523 (),
524 ),
525 (
526 r'GetDeferredQuitTaskForRunLoop',
527 (
528 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
529 "gab@ if you found a use case where this is the only solution.",
530 ),
531 False,
532 (),
533 ),
534 (
Victor Costan3653df62018-02-08 21:38:16535 'sqlite3_initialize',
536 (
537 'Instead of sqlite3_initialize, depend on //sql, ',
538 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
539 ),
540 True,
541 (
542 r'^sql/initialization\.(cc|h)$',
543 r'^third_party/sqlite/.*\.(c|cc|h)$',
544 ),
545 ),
[email protected]127f18ec2012-06-16 05:05:59546)
547
wnwenbdc444e2016-05-25 13:44:15548
mlamouria82272622014-09-16 18:45:04549_IPC_ENUM_TRAITS_DEPRECATED = (
550 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50551 'See http://www.chromium.org/Home/chromium-security/education/'
552 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:04553
Shenghua Zhangbfaa38b82017-11-16 21:58:02554_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
555 r".*[\\\/]BuildHooksAndroidImpl\.java",
556 r".*[\\\/]LicenseContentProvider\.java",
557]
[email protected]127f18ec2012-06-16 05:05:59558
Sean Kau46e29bc2017-08-28 16:31:16559# These paths contain test data and other known invalid JSON files.
560_KNOWN_INVALID_JSON_FILE_PATTERNS = [
561 r'test[\\\/]data[\\\/]',
562 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
563 r'^third_party[\\\/]protobuf[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16564 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Sean Kau46e29bc2017-08-28 16:31:16565]
566
567
[email protected]b00342e7f2013-03-26 16:21:54568_VALID_OS_MACROS = (
569 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08570 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54571 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:12572 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:54573 'OS_BSD',
574 'OS_CAT', # For testing.
575 'OS_CHROMEOS',
576 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37577 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54578 'OS_IOS',
579 'OS_LINUX',
580 'OS_MACOSX',
581 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21582 'OS_NACL_NONSFI',
583 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12584 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54585 'OS_OPENBSD',
586 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37587 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54588 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54589 'OS_WIN',
590)
591
592
agrievef32bcc72016-04-04 14:57:40593_ANDROID_SPECIFIC_PYDEPS_FILES = [
594 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04595 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58596 'build/secondary/third_party/android_platform/'
597 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19598 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40599]
600
wnwenbdc444e2016-05-25 13:44:15601
agrievef32bcc72016-04-04 14:57:40602_GENERIC_PYDEPS_FILES = [
John Chencde89192018-01-27 21:18:40603 'chrome/test/chromedriver/test/run_py_tests.pydeps',
agrievef32bcc72016-04-04 14:57:40604]
605
wnwenbdc444e2016-05-25 13:44:15606
agrievef32bcc72016-04-04 14:57:40607_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
608
609
Eric Boren6fd2b932018-01-25 15:05:08610# Bypass the AUTHORS check for these accounts.
611_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:29612 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
613 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
614 'fuchsia-sdk', 'nacl', 'pdfium', 'skia', 'src-internal', 'webrtc')
615 ) | set('%[email protected]' % s for s in ('findit-for-me',))
Eric Boren6fd2b932018-01-25 15:05:08616
617
[email protected]55459852011-08-10 15:17:19618def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
619 """Attempts to prevent use of functions intended only for testing in
620 non-testing code. For now this is just a best-effort implementation
621 that ignores header files and may have some false positives. A
622 better implementation would probably need a proper C++ parser.
623 """
624 # We only scan .cc files and the like, as the declaration of
625 # for-testing functions in header files are hard to distinguish from
626 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44627 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19628
jochenc0d4808c2015-07-27 09:25:42629 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19630 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09631 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19632 exclusion_pattern = input_api.re.compile(
633 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
634 base_function_pattern, base_function_pattern))
635
636 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44637 black_list = (_EXCLUDED_PATHS +
638 _TEST_CODE_EXCLUDED_PATHS +
639 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19640 return input_api.FilterSourceFile(
641 affected_file,
642 white_list=(file_inclusion_pattern, ),
643 black_list=black_list)
644
645 problems = []
646 for f in input_api.AffectedSourceFiles(FilterFile):
647 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24648 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03649 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46650 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03651 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19652 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03653 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19654
655 if problems:
[email protected]f7051d52013-04-02 18:31:42656 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03657 else:
658 return []
[email protected]55459852011-08-10 15:17:19659
660
Vaclav Brozek7dbc28c2018-03-27 08:35:23661def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
662 """This is a simplified version of
663 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
664 """
665 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
666 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
667 name_pattern = r'ForTest(s|ing)?'
668 # Describes an occurrence of "ForTest*" inside a // comment.
669 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
670 # Catch calls.
671 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
672 # Ignore definitions. (Comments are ignored separately.)
673 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
674
675 problems = []
676 sources = lambda x: input_api.FilterSourceFile(
677 x,
678 black_list=(('(?i).*test', r'.*\/junit\/')
679 + input_api.DEFAULT_BLACK_LIST),
680 white_list=(r'.*\.java$',)
681 )
682 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
683 local_path = f.LocalPath()
684 is_inside_javadoc = False
685 for line_number, line in f.ChangedContents():
686 if is_inside_javadoc and javadoc_end_re.search(line):
687 is_inside_javadoc = False
688 if not is_inside_javadoc and javadoc_start_re.search(line):
689 is_inside_javadoc = True
690 if is_inside_javadoc:
691 continue
692 if (inclusion_re.search(line) and
693 not comment_re.search(line) and
694 not exclusion_re.search(line)):
695 problems.append(
696 '%s:%d\n %s' % (local_path, line_number, line.strip()))
697
698 if problems:
699 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
700 else:
701 return []
702
703
[email protected]10689ca2011-09-02 02:31:54704def _CheckNoIOStreamInHeaders(input_api, output_api):
705 """Checks to make sure no .h files include <iostream>."""
706 files = []
707 pattern = input_api.re.compile(r'^#include\s*<iostream>',
708 input_api.re.MULTILINE)
709 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
710 if not f.LocalPath().endswith('.h'):
711 continue
712 contents = input_api.ReadFile(f)
713 if pattern.search(contents):
714 files.append(f)
715
716 if len(files):
yolandyandaabc6d2016-04-18 18:29:39717 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06718 'Do not #include <iostream> in header files, since it inserts static '
719 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54720 '#include <ostream>. See http://crbug.com/94794',
721 files) ]
722 return []
723
724
[email protected]72df4e782012-06-21 16:28:18725def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52726 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18727 problems = []
728 for f in input_api.AffectedFiles():
729 if (not f.LocalPath().endswith(('.cc', '.mm'))):
730 continue
731
732 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04733 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18734 problems.append(' %s:%d' % (f.LocalPath(), line_num))
735
736 if not problems:
737 return []
738 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
739 '\n'.join(problems))]
740
741
danakj61c1aa22015-10-26 19:55:52742def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57743 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52744 errors = []
745 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
746 input_api.re.MULTILINE)
747 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
748 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
749 continue
750 for lnum, line in f.ChangedContents():
751 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17752 errors.append(output_api.PresubmitError(
753 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57754 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17755 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52756 return errors
757
758
mcasasb7440c282015-02-04 14:52:19759def _FindHistogramNameInLine(histogram_name, line):
760 """Tries to find a histogram name or prefix in a line."""
761 if not "affected-histogram" in line:
762 return histogram_name in line
763 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
764 # the histogram_name.
765 if not '"' in line:
766 return False
767 histogram_prefix = line.split('\"')[1]
768 return histogram_prefix in histogram_name
769
770
771def _CheckUmaHistogramChanges(input_api, output_api):
772 """Check that UMA histogram names in touched lines can still be found in other
773 lines of the patch or in histograms.xml. Note that this check would not catch
774 the reverse: changes in histograms.xml not matched in the code itself."""
775 touched_histograms = []
776 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:47777 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
778 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
779 name_pattern = r'"(.*?)"'
780 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
781 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
782 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
783 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
784 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:17785 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:19786 for f in input_api.AffectedFiles():
787 # If histograms.xml itself is modified, keep the modified lines for later.
788 if f.LocalPath().endswith(('histograms.xml')):
789 histograms_xml_modifications = f.ChangedContents()
790 continue
Vaclav Brozekbdac817c2018-03-24 06:30:47791 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
792 single_line_re = single_line_c_re
793 split_line_prefix_re = split_line_c_prefix_re
794 elif f.LocalPath().endswith(('java')):
795 single_line_re = single_line_java_re
796 split_line_prefix_re = split_line_java_prefix_re
797 else:
mcasasb7440c282015-02-04 14:52:19798 continue
799 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:17800 if last_line_matched_prefix:
801 suffix_found = split_line_suffix_re.search(line)
802 if suffix_found :
803 touched_histograms.append([suffix_found.group(1), f, line_num])
804 last_line_matched_prefix = False
805 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:06806 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:19807 if found:
808 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:17809 continue
810 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:19811
812 # Search for the touched histogram names in the local modifications to
813 # histograms.xml, and, if not found, on the base histograms.xml file.
814 unmatched_histograms = []
815 for histogram_info in touched_histograms:
816 histogram_name_found = False
817 for line_num, line in histograms_xml_modifications:
818 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
819 if histogram_name_found:
820 break
821 if not histogram_name_found:
822 unmatched_histograms.append(histogram_info)
823
eromanb90c82e7e32015-04-01 15:13:49824 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19825 problems = []
826 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49827 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19828 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45829 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19830 histogram_name_found = False
831 for line in histograms_xml:
832 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
833 if histogram_name_found:
834 break
835 if not histogram_name_found:
836 problems.append(' [%s:%d] %s' %
837 (f.LocalPath(), line_num, histogram_name))
838
839 if not problems:
840 return []
841 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
842 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49843 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19844
wnwenbdc444e2016-05-25 13:44:15845
yolandyandaabc6d2016-04-18 18:29:39846def _CheckFlakyTestUsage(input_api, output_api):
847 """Check that FlakyTest annotation is our own instead of the android one"""
848 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
849 files = []
850 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
851 if f.LocalPath().endswith('Test.java'):
852 if pattern.search(input_api.ReadFile(f)):
853 files.append(f)
854 if len(files):
855 return [output_api.PresubmitError(
856 'Use org.chromium.base.test.util.FlakyTest instead of '
857 'android.test.FlakyTest',
858 files)]
859 return []
mcasasb7440c282015-02-04 14:52:19860
wnwenbdc444e2016-05-25 13:44:15861
[email protected]8ea5d4b2011-09-13 21:49:22862def _CheckNoNewWStrings(input_api, output_api):
863 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27864 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22865 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20866 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57867 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34868 '/win/' in f.LocalPath() or
869 'chrome_elf' in f.LocalPath() or
870 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20871 continue
[email protected]8ea5d4b2011-09-13 21:49:22872
[email protected]a11dbe9b2012-08-07 01:32:58873 allowWString = False
[email protected]b5c24292011-11-28 14:38:20874 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58875 if 'presubmit: allow wstring' in line:
876 allowWString = True
877 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27878 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58879 allowWString = False
880 else:
881 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22882
[email protected]55463aa62011-10-12 00:48:27883 if not problems:
884 return []
885 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58886 ' If you are calling a cross-platform API that accepts a wstring, '
887 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27888 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22889
890
[email protected]2a8ac9c2011-10-19 17:20:44891def _CheckNoDEPSGIT(input_api, output_api):
892 """Make sure .DEPS.git is never modified manually."""
893 if any(f.LocalPath().endswith('.DEPS.git') for f in
894 input_api.AffectedFiles()):
895 return [output_api.PresubmitError(
896 'Never commit changes to .DEPS.git. This file is maintained by an\n'
897 'automated system based on what\'s in DEPS and your changes will be\n'
898 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50899 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
900 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:44901 'for more information')]
902 return []
903
904
tandriief664692014-09-23 14:51:47905def _CheckValidHostsInDEPS(input_api, output_api):
906 """Checks that DEPS file deps are from allowed_hosts."""
907 # Run only if DEPS file has been modified to annoy fewer bystanders.
908 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
909 return []
910 # Outsource work to gclient verify
911 try:
912 input_api.subprocess.check_output(['gclient', 'verify'])
913 return []
914 except input_api.subprocess.CalledProcessError, error:
915 return [output_api.PresubmitError(
916 'DEPS file must have only git dependencies.',
917 long_text=error.output)]
918
919
[email protected]127f18ec2012-06-16 05:05:59920def _CheckNoBannedFunctions(input_api, output_api):
921 """Make sure that banned functions are not used."""
922 warnings = []
923 errors = []
924
wnwenbdc444e2016-05-25 13:44:15925 def IsBlacklisted(affected_file, blacklist):
926 local_path = affected_file.LocalPath()
927 for item in blacklist:
928 if input_api.re.match(item, local_path):
929 return True
930 return False
931
Sylvain Defresnea8b73d252018-02-28 15:45:54932 def IsIosObcjFile(affected_file):
933 local_path = affected_file.LocalPath()
934 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
935 return False
936 basename = input_api.os_path.basename(local_path)
937 if 'ios' in basename.split('_'):
938 return True
939 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
940 if sep and 'ios' in local_path.split(sep):
941 return True
942 return False
943
wnwenbdc444e2016-05-25 13:44:15944 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
945 matched = False
946 if func_name[0:1] == '/':
947 regex = func_name[1:]
948 if input_api.re.search(regex, line):
949 matched = True
950 elif func_name in line:
dchenge07de812016-06-20 19:27:17951 matched = True
wnwenbdc444e2016-05-25 13:44:15952 if matched:
dchenge07de812016-06-20 19:27:17953 problems = warnings
wnwenbdc444e2016-05-25 13:44:15954 if error:
dchenge07de812016-06-20 19:27:17955 problems = errors
wnwenbdc444e2016-05-25 13:44:15956 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
957 for message_line in message:
958 problems.append(' %s' % message_line)
959
Eric Stevensona9a980972017-09-23 00:04:41960 file_filter = lambda f: f.LocalPath().endswith(('.java'))
961 for f in input_api.AffectedFiles(file_filter=file_filter):
962 for line_num, line in f.ChangedContents():
963 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
964 CheckForMatch(f, line_num, line, func_name, message, error)
965
[email protected]127f18ec2012-06-16 05:05:59966 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
967 for f in input_api.AffectedFiles(file_filter=file_filter):
968 for line_num, line in f.ChangedContents():
969 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15970 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59971
Sylvain Defresnea8b73d252018-02-28 15:45:54972 for f in input_api.AffectedFiles(file_filter=IsIosObcjFile):
973 for line_num, line in f.ChangedContents():
974 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
975 CheckForMatch(f, line_num, line, func_name, message, error)
976
[email protected]127f18ec2012-06-16 05:05:59977 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
978 for f in input_api.AffectedFiles(file_filter=file_filter):
979 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49980 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49981 if IsBlacklisted(f, excluded_paths):
982 continue
wnwenbdc444e2016-05-25 13:44:15983 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59984
985 result = []
986 if (warnings):
987 result.append(output_api.PresubmitPromptWarning(
988 'Banned functions were used.\n' + '\n'.join(warnings)))
989 if (errors):
990 result.append(output_api.PresubmitError(
991 'Banned functions were used.\n' + '\n'.join(errors)))
992 return result
993
994
[email protected]6c063c62012-07-11 19:11:06995def _CheckNoPragmaOnce(input_api, output_api):
996 """Make sure that banned functions are not used."""
997 files = []
998 pattern = input_api.re.compile(r'^#pragma\s+once',
999 input_api.re.MULTILINE)
1000 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1001 if not f.LocalPath().endswith('.h'):
1002 continue
1003 contents = input_api.ReadFile(f)
1004 if pattern.search(contents):
1005 files.append(f)
1006
1007 if files:
1008 return [output_api.PresubmitError(
1009 'Do not use #pragma once in header files.\n'
1010 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1011 files)]
1012 return []
1013
[email protected]127f18ec2012-06-16 05:05:591014
[email protected]e7479052012-09-19 00:26:121015def _CheckNoTrinaryTrueFalse(input_api, output_api):
1016 """Checks to make sure we don't introduce use of foo ? true : false."""
1017 problems = []
1018 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1019 for f in input_api.AffectedFiles():
1020 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1021 continue
1022
1023 for line_num, line in f.ChangedContents():
1024 if pattern.match(line):
1025 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1026
1027 if not problems:
1028 return []
1029 return [output_api.PresubmitPromptWarning(
1030 'Please consider avoiding the "? true : false" pattern if possible.\n' +
1031 '\n'.join(problems))]
1032
1033
[email protected]55f9f382012-07-31 11:02:181034def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:281035 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:181036 change. Breaking - rules is an error, breaking ! rules is a
1037 warning.
1038 """
mohan.reddyf21db962014-10-16 12:26:471039 import sys
[email protected]55f9f382012-07-31 11:02:181040 # We need to wait until we have an input_api object and use this
1041 # roundabout construct to import checkdeps because this file is
1042 # eval-ed and thus doesn't have __file__.
1043 original_sys_path = sys.path
1044 try:
1045 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:471046 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:181047 import checkdeps
1048 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:241049 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:281050 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:181051 from rules import Rule
1052 finally:
1053 # Restore sys.path to what it was before.
1054 sys.path = original_sys_path
1055
1056 added_includes = []
rhalavati08acd232017-04-03 07:23:281057 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:241058 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:181059 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:281060 if CppChecker.IsCppFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501061 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081062 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:281063 elif ProtoChecker.IsProtoFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501064 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081065 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:241066 elif JavaChecker.IsJavaFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501067 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081068 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:181069
[email protected]26385172013-05-09 23:11:351070 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181071
1072 error_descriptions = []
1073 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:281074 error_subjects = set()
1075 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:181076 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
1077 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:081078 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181079 description_with_path = '%s\n %s' % (path, rule_description)
1080 if rule_type == Rule.DISALLOW:
1081 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281082 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:181083 else:
1084 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281085 warning_subjects.add("#includes")
1086
1087 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
1088 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:081089 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:281090 description_with_path = '%s\n %s' % (path, rule_description)
1091 if rule_type == Rule.DISALLOW:
1092 error_descriptions.append(description_with_path)
1093 error_subjects.add("imports")
1094 else:
1095 warning_descriptions.append(description_with_path)
1096 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:181097
Jinsuk Kim5a092672017-10-24 22:42:241098 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:021099 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:081100 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:241101 description_with_path = '%s\n %s' % (path, rule_description)
1102 if rule_type == Rule.DISALLOW:
1103 error_descriptions.append(description_with_path)
1104 error_subjects.add("imports")
1105 else:
1106 warning_descriptions.append(description_with_path)
1107 warning_subjects.add("imports")
1108
[email protected]55f9f382012-07-31 11:02:181109 results = []
1110 if error_descriptions:
1111 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:281112 'You added one or more %s that violate checkdeps rules.'
1113 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:181114 error_descriptions))
1115 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:421116 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:281117 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:181118 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:281119 '%s? See relevant DEPS file(s) for details and contacts.' %
1120 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:181121 warning_descriptions))
1122 return results
1123
1124
[email protected]fbcafe5a2012-08-08 15:31:221125def _CheckFilePermissions(input_api, output_api):
1126 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:151127 if input_api.platform == 'win32':
1128 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:291129 checkperms_tool = input_api.os_path.join(
1130 input_api.PresubmitLocalPath(),
1131 'tools', 'checkperms', 'checkperms.py')
1132 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:471133 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:391134 with input_api.CreateTemporaryFile() as file_list:
1135 for f in input_api.AffectedFiles():
1136 # checkperms.py file/directory arguments must be relative to the
1137 # repository.
1138 file_list.write(f.LocalPath() + '\n')
1139 file_list.close()
1140 args += ['--file-list', file_list.name]
1141 try:
1142 input_api.subprocess.check_output(args)
1143 return []
1144 except input_api.subprocess.CalledProcessError as error:
1145 return [output_api.PresubmitError(
1146 'checkperms.py failed:',
1147 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:221148
1149
robertocn832f5992017-01-04 19:01:301150def _CheckTeamTags(input_api, output_api):
1151 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
1152 checkteamtags_tool = input_api.os_path.join(
1153 input_api.PresubmitLocalPath(),
1154 'tools', 'checkteamtags', 'checkteamtags.py')
1155 args = [input_api.python_executable, checkteamtags_tool,
1156 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:221157 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:301158 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
1159 'OWNERS']
1160 try:
1161 if files:
1162 input_api.subprocess.check_output(args + files)
1163 return []
1164 except input_api.subprocess.CalledProcessError as error:
1165 return [output_api.PresubmitError(
1166 'checkteamtags.py failed:',
1167 long_text=error.output)]
1168
1169
[email protected]c8278b32012-10-30 20:35:491170def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
1171 """Makes sure we don't include ui/aura/window_property.h
1172 in header files.
1173 """
1174 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1175 errors = []
1176 for f in input_api.AffectedFiles():
1177 if not f.LocalPath().endswith('.h'):
1178 continue
1179 for line_num, line in f.ChangedContents():
1180 if pattern.match(line):
1181 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1182
1183 results = []
1184 if errors:
1185 results.append(output_api.PresubmitError(
1186 'Header files should not include ui/aura/window_property.h', errors))
1187 return results
1188
1189
[email protected]70ca77752012-11-20 03:45:031190def _CheckForVersionControlConflictsInFile(input_api, f):
1191 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1192 errors = []
1193 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231194 if f.LocalPath().endswith('.md'):
1195 # First-level headers in markdown look a lot like version control
1196 # conflict markers. http://daringfireball.net/projects/markdown/basics
1197 continue
[email protected]70ca77752012-11-20 03:45:031198 if pattern.match(line):
1199 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1200 return errors
1201
1202
1203def _CheckForVersionControlConflicts(input_api, output_api):
1204 """Usually this is not intentional and will cause a compile failure."""
1205 errors = []
1206 for f in input_api.AffectedFiles():
1207 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1208
1209 results = []
1210 if errors:
1211 results.append(output_api.PresubmitError(
1212 'Version control conflict markers found, please resolve.', errors))
1213 return results
1214
estadee17314a02017-01-12 16:22:161215def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1216 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1217 errors = []
1218 for f in input_api.AffectedFiles():
1219 for line_num, line in f.ChangedContents():
1220 if pattern.search(line):
1221 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1222
1223 results = []
1224 if errors:
1225 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:501226 'Found Google support URL addressed by answer number. Please replace '
1227 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:161228 return results
1229
[email protected]70ca77752012-11-20 03:45:031230
[email protected]06e6d0ff2012-12-11 01:36:441231def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1232 def FilterFile(affected_file):
1233 """Filter function for use with input_api.AffectedSourceFiles,
1234 below. This filters out everything except non-test files from
1235 top-level directories that generally speaking should not hard-code
1236 service URLs (e.g. src/android_webview/, src/content/ and others).
1237 """
1238 return input_api.FilterSourceFile(
1239 affected_file,
[email protected]78bb39d62012-12-11 15:11:561240 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441241 black_list=(_EXCLUDED_PATHS +
1242 _TEST_CODE_EXCLUDED_PATHS +
1243 input_api.DEFAULT_BLACK_LIST))
1244
reillyi38965732015-11-16 18:27:331245 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1246 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461247 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1248 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441249 problems = [] # items are (filename, line_number, line)
1250 for f in input_api.AffectedSourceFiles(FilterFile):
1251 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461252 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441253 problems.append((f.LocalPath(), line_num, line))
1254
1255 if problems:
[email protected]f7051d52013-04-02 18:31:421256 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441257 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581258 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441259 [' %s:%d: %s' % (
1260 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031261 else:
1262 return []
[email protected]06e6d0ff2012-12-11 01:36:441263
1264
[email protected]d2530012013-01-25 16:39:271265def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1266 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311267 The native_client_sdk directory is excluded because it has auto-generated PNG
1268 files for documentation.
[email protected]d2530012013-01-25 16:39:271269 """
[email protected]d2530012013-01-25 16:39:271270 errors = []
binji0dcdf342014-12-12 18:32:311271 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1272 black_list = (r'^native_client_sdk[\\\/]',)
1273 file_filter = lambda f: input_api.FilterSourceFile(
1274 f, white_list=white_list, black_list=black_list)
1275 for f in input_api.AffectedFiles(include_deletes=False,
1276 file_filter=file_filter):
1277 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271278
1279 results = []
1280 if errors:
1281 results.append(output_api.PresubmitError(
1282 'The name of PNG files should not have abbreviations. \n'
1283 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1284 'Contact [email protected] if you have questions.', errors))
1285 return results
1286
1287
Daniel Cheng4dcdb6b2017-04-13 08:30:171288def _ExtractAddRulesFromParsedDeps(parsed_deps):
1289 """Extract the rules that add dependencies from a parsed DEPS file.
1290
1291 Args:
1292 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1293 add_rules = set()
1294 add_rules.update([
1295 rule[1:] for rule in parsed_deps.get('include_rules', [])
1296 if rule.startswith('+') or rule.startswith('!')
1297 ])
Vaclav Brozekd5de76a2018-03-17 07:57:501298 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:171299 {}).iteritems():
1300 add_rules.update([
1301 rule[1:] for rule in rules
1302 if rule.startswith('+') or rule.startswith('!')
1303 ])
1304 return add_rules
1305
1306
1307def _ParseDeps(contents):
1308 """Simple helper for parsing DEPS files."""
1309 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171310 class _VarImpl:
1311
1312 def __init__(self, local_scope):
1313 self._local_scope = local_scope
1314
1315 def Lookup(self, var_name):
1316 """Implements the Var syntax."""
1317 try:
1318 return self._local_scope['vars'][var_name]
1319 except KeyError:
1320 raise Exception('Var is not defined: %s' % var_name)
1321
1322 local_scope = {}
1323 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171324 'Var': _VarImpl(local_scope).Lookup,
1325 }
1326 exec contents in global_scope, local_scope
1327 return local_scope
1328
1329
1330def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081331 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411332 a set of DEPS entries that we should look up.
1333
1334 For a directory (rather than a specific filename) we fake a path to
1335 a specific filename by adding /DEPS. This is chosen as a file that
1336 will seldom or never be subject to per-file include_rules.
1337 """
[email protected]2b438d62013-11-14 17:54:141338 # We ignore deps entries on auto-generated directories.
1339 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081340
Daniel Cheng4dcdb6b2017-04-13 08:30:171341 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1342 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1343
1344 added_deps = new_deps.difference(old_deps)
1345
[email protected]2b438d62013-11-14 17:54:141346 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171347 for added_dep in added_deps:
1348 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1349 continue
1350 # Assume that a rule that ends in .h is a rule for a specific file.
1351 if added_dep.endswith('.h'):
1352 results.add(added_dep)
1353 else:
1354 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081355 return results
1356
1357
[email protected]e871964c2013-05-13 14:14:551358def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1359 """When a dependency prefixed with + is added to a DEPS file, we
1360 want to make sure that the change is reviewed by an OWNER of the
1361 target file or directory, to avoid layering violations from being
1362 introduced. This check verifies that this happens.
1363 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171364 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241365
1366 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191367 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241368 for f in input_api.AffectedFiles(include_deletes=False,
1369 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551370 filename = input_api.os_path.basename(f.LocalPath())
1371 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171372 virtual_depended_on_files.update(_CalculateAddedDeps(
1373 input_api.os_path,
1374 '\n'.join(f.OldContents()),
1375 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551376
[email protected]e871964c2013-05-13 14:14:551377 if not virtual_depended_on_files:
1378 return []
1379
1380 if input_api.is_committing:
1381 if input_api.tbr:
1382 return [output_api.PresubmitNotifyResult(
1383 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271384 if input_api.dry_run:
1385 return [output_api.PresubmitNotifyResult(
1386 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551387 if not input_api.change.issue:
1388 return [output_api.PresubmitError(
1389 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401390 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551391 output = output_api.PresubmitError
1392 else:
1393 output = output_api.PresubmitNotifyResult
1394
1395 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501396 owner_email, reviewers = (
1397 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1398 input_api,
1399 owners_db.email_regexp,
1400 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551401
1402 owner_email = owner_email or input_api.change.author_email
1403
[email protected]de4f7d22013-05-23 14:27:461404 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511405 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461406 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551407 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1408 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411409
1410 # We strip the /DEPS part that was added by
1411 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1412 # directory.
1413 def StripDeps(path):
1414 start_deps = path.rfind('/DEPS')
1415 if start_deps != -1:
1416 return path[:start_deps]
1417 else:
1418 return path
1419 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551420 for path in missing_files]
1421
1422 if unapproved_dependencies:
1423 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151424 output('You need LGTM from owners of depends-on paths in DEPS that were '
1425 'modified in this CL:\n %s' %
1426 '\n '.join(sorted(unapproved_dependencies)))]
1427 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1428 output_list.append(output(
1429 'Suggested missing target path OWNERS:\n %s' %
1430 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551431 return output_list
1432
1433 return []
1434
1435
[email protected]85218562013-11-22 07:41:401436def _CheckSpamLogging(input_api, output_api):
1437 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1438 black_list = (_EXCLUDED_PATHS +
1439 _TEST_CODE_EXCLUDED_PATHS +
1440 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501441 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191442 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481443 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461444 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121445 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1446 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581447 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161448 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031449 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151450 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1451 r"^chromecast[\\\/]",
1452 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481453 r"^components[\\\/]browser_watcher[\\\/]"
1454 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311455 r"^components[\\\/]html_viewer[\\\/]"
1456 r"web_test_delegate_impl\.cc$",
Samuel Huang577ef6c2018-03-13 18:19:341457 r"^components[\\\/]zucchini[\\\/].*",
peter80739bb2015-10-20 11:17:461458 # TODO(peter): Remove this exception. https://crbug.com/534537
1459 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1460 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251461 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1462 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241463 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111464 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151465 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111466 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521467 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501468 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361469 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311470 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131471 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001472 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441473 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451474 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021475 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351476 r"dump_file_system.cc$",
1477 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401478 source_file_filter = lambda x: input_api.FilterSourceFile(
1479 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1480
thomasanderson625d3932017-03-29 07:16:581481 log_info = set([])
1482 printf = set([])
[email protected]85218562013-11-22 07:41:401483
1484 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581485 for _, line in f.ChangedContents():
1486 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1487 log_info.add(f.LocalPath())
1488 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1489 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371490
thomasanderson625d3932017-03-29 07:16:581491 if input_api.re.search(r"\bprintf\(", line):
1492 printf.add(f.LocalPath())
1493 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1494 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401495
1496 if log_info:
1497 return [output_api.PresubmitError(
1498 'These files spam the console log with LOG(INFO):',
1499 items=log_info)]
1500 if printf:
1501 return [output_api.PresubmitError(
1502 'These files spam the console log with printf/fprintf:',
1503 items=printf)]
1504 return []
1505
1506
[email protected]49aa76a2013-12-04 06:59:161507def _CheckForAnonymousVariables(input_api, output_api):
1508 """These types are all expected to hold locks while in scope and
1509 so should never be anonymous (which causes them to be immediately
1510 destroyed)."""
1511 they_who_must_be_named = [
1512 'base::AutoLock',
1513 'base::AutoReset',
1514 'base::AutoUnlock',
1515 'SkAutoAlphaRestore',
1516 'SkAutoBitmapShaderInstall',
1517 'SkAutoBlitterChoose',
1518 'SkAutoBounderCommit',
1519 'SkAutoCallProc',
1520 'SkAutoCanvasRestore',
1521 'SkAutoCommentBlock',
1522 'SkAutoDescriptor',
1523 'SkAutoDisableDirectionCheck',
1524 'SkAutoDisableOvalCheck',
1525 'SkAutoFree',
1526 'SkAutoGlyphCache',
1527 'SkAutoHDC',
1528 'SkAutoLockColors',
1529 'SkAutoLockPixels',
1530 'SkAutoMalloc',
1531 'SkAutoMaskFreeImage',
1532 'SkAutoMutexAcquire',
1533 'SkAutoPathBoundsUpdate',
1534 'SkAutoPDFRelease',
1535 'SkAutoRasterClipValidate',
1536 'SkAutoRef',
1537 'SkAutoTime',
1538 'SkAutoTrace',
1539 'SkAutoUnref',
1540 ]
1541 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1542 # bad: base::AutoLock(lock.get());
1543 # not bad: base::AutoLock lock(lock.get());
1544 bad_pattern = input_api.re.compile(anonymous)
1545 # good: new base::AutoLock(lock.get())
1546 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1547 errors = []
1548
1549 for f in input_api.AffectedFiles():
1550 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1551 continue
1552 for linenum, line in f.ChangedContents():
1553 if bad_pattern.search(line) and not good_pattern.search(line):
1554 errors.append('%s:%d' % (f.LocalPath(), linenum))
1555
1556 if errors:
1557 return [output_api.PresubmitError(
1558 'These lines create anonymous variables that need to be named:',
1559 items=errors)]
1560 return []
1561
1562
Peter Kasting4844e46e2018-02-23 07:27:101563def _CheckUniquePtr(input_api, output_api):
1564 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1565 sources = lambda affected_file: input_api.FilterSourceFile(
1566 affected_file,
1567 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1568 input_api.DEFAULT_BLACK_LIST),
1569 white_list=(file_inclusion_pattern,))
1570 return_construct_pattern = input_api.re.compile(
1571 r'(=|\breturn)\s*std::unique_ptr<.*?(?<!])>\([^)]+\)')
1572 null_construct_pattern = input_api.re.compile(
1573 r'\b(?<!<)std::unique_ptr<.*?>\(\)')
1574 errors = []
1575 for f in input_api.AffectedSourceFiles(sources):
1576 for line_number, line in f.ChangedContents():
1577 # Disallow:
1578 # return std::unique_ptr<T>(foo);
1579 # bar = std::unique_ptr<T>(foo);
1580 # But allow:
1581 # return std::unique_ptr<T[]>(foo);
1582 # bar = std::unique_ptr<T[]>(foo);
1583 if return_construct_pattern.search(line):
1584 errors.append(output_api.PresubmitError(
1585 ('%s:%d uses explicit std::unique_ptr constructor. ' +
1586 'Use std::make_unique<T>() instead.') %
1587 (f.LocalPath(), line_number)))
1588 # Disallow:
1589 # std::unique_ptr<T>()
1590 if null_construct_pattern.search(line):
1591 errors.append(output_api.PresubmitError(
1592 '%s:%d uses std::unique_ptr<T>(). Use nullptr instead.' %
1593 (f.LocalPath(), line_number)))
1594 return errors
1595
1596
[email protected]999261d2014-03-03 20:08:081597def _CheckUserActionUpdate(input_api, output_api):
1598 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521599 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081600 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521601 # If actions.xml is already included in the changelist, the PRESUBMIT
1602 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081603 return []
1604
[email protected]999261d2014-03-03 20:08:081605 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1606 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521607 current_actions = None
[email protected]999261d2014-03-03 20:08:081608 for f in input_api.AffectedFiles(file_filter=file_filter):
1609 for line_num, line in f.ChangedContents():
1610 match = input_api.re.search(action_re, line)
1611 if match:
[email protected]2f92dec2014-03-07 19:21:521612 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1613 # loaded only once.
1614 if not current_actions:
1615 with open('tools/metrics/actions/actions.xml') as actions_f:
1616 current_actions = actions_f.read()
1617 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081618 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521619 action = 'name="{0}"'.format(action_name)
1620 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081621 return [output_api.PresubmitPromptWarning(
1622 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521623 'tools/metrics/actions/actions.xml. Please run '
1624 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081625 % (f.LocalPath(), line_num, action_name))]
1626 return []
1627
1628
Daniel Cheng13ca61a882017-08-25 15:11:251629def _ImportJSONCommentEater(input_api):
1630 import sys
1631 sys.path = sys.path + [input_api.os_path.join(
1632 input_api.PresubmitLocalPath(),
1633 'tools', 'json_comment_eater')]
1634 import json_comment_eater
1635 return json_comment_eater
1636
1637
[email protected]99171a92014-06-03 08:44:471638def _GetJSONParseError(input_api, filename, eat_comments=True):
1639 try:
1640 contents = input_api.ReadFile(filename)
1641 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251642 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131643 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471644
1645 input_api.json.loads(contents)
1646 except ValueError as e:
1647 return e
1648 return None
1649
1650
1651def _GetIDLParseError(input_api, filename):
1652 try:
1653 contents = input_api.ReadFile(filename)
1654 idl_schema = input_api.os_path.join(
1655 input_api.PresubmitLocalPath(),
1656 'tools', 'json_schema_compiler', 'idl_schema.py')
1657 process = input_api.subprocess.Popen(
1658 [input_api.python_executable, idl_schema],
1659 stdin=input_api.subprocess.PIPE,
1660 stdout=input_api.subprocess.PIPE,
1661 stderr=input_api.subprocess.PIPE,
1662 universal_newlines=True)
1663 (_, error) = process.communicate(input=contents)
1664 return error or None
1665 except ValueError as e:
1666 return e
1667
1668
1669def _CheckParseErrors(input_api, output_api):
1670 """Check that IDL and JSON files do not contain syntax errors."""
1671 actions = {
1672 '.idl': _GetIDLParseError,
1673 '.json': _GetJSONParseError,
1674 }
[email protected]99171a92014-06-03 08:44:471675 # Most JSON files are preprocessed and support comments, but these do not.
1676 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491677 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471678 ]
1679 # Only run IDL checker on files in these directories.
1680 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491681 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1682 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471683 ]
1684
1685 def get_action(affected_file):
1686 filename = affected_file.LocalPath()
1687 return actions.get(input_api.os_path.splitext(filename)[1])
1688
[email protected]99171a92014-06-03 08:44:471689 def FilterFile(affected_file):
1690 action = get_action(affected_file)
1691 if not action:
1692 return False
1693 path = affected_file.LocalPath()
1694
Sean Kau46e29bc2017-08-28 16:31:161695 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471696 return False
1697
1698 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161699 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471700 return False
1701 return True
1702
1703 results = []
1704 for affected_file in input_api.AffectedFiles(
1705 file_filter=FilterFile, include_deletes=False):
1706 action = get_action(affected_file)
1707 kwargs = {}
1708 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161709 _MatchesFile(input_api, json_no_comments_patterns,
1710 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471711 kwargs['eat_comments'] = False
1712 parse_error = action(input_api,
1713 affected_file.AbsoluteLocalPath(),
1714 **kwargs)
1715 if parse_error:
1716 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1717 (affected_file.LocalPath(), parse_error)))
1718 return results
1719
1720
[email protected]760deea2013-12-10 19:33:491721def _CheckJavaStyle(input_api, output_api):
1722 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471723 import sys
[email protected]760deea2013-12-10 19:33:491724 original_sys_path = sys.path
1725 try:
1726 sys.path = sys.path + [input_api.os_path.join(
1727 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1728 import checkstyle
1729 finally:
1730 # Restore sys.path to what it was before.
1731 sys.path = original_sys_path
1732
1733 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091734 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511735 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491736
1737
Sean Kau46e29bc2017-08-28 16:31:161738def _MatchesFile(input_api, patterns, path):
1739 for pattern in patterns:
1740 if input_api.re.search(pattern, path):
1741 return True
1742 return False
1743
1744
Daniel Cheng7052cdf2017-11-21 19:23:291745def _GetOwnersFilesToCheckForIpcOwners(input_api):
1746 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:171747
Daniel Cheng7052cdf2017-11-21 19:23:291748 Returns:
1749 A dictionary mapping an OWNER file to the list of OWNERS rules it must
1750 contain to cover IPC-related files with noparent reviewer rules.
1751 """
1752 # Whether or not a file affects IPC is (mostly) determined by a simple list
1753 # of filename patterns.
dchenge07de812016-06-20 19:27:171754 file_patterns = [
palmerb19a0932017-01-24 04:00:311755 # Legacy IPC:
dchenge07de812016-06-20 19:27:171756 '*_messages.cc',
1757 '*_messages*.h',
1758 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311759 # Mojo IPC:
dchenge07de812016-06-20 19:27:171760 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:471761 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:171762 '*_struct_traits*.*',
1763 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311764 '*.typemap',
1765 # Android native IPC:
1766 '*.aidl',
1767 # Blink uses a different file naming convention:
1768 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:471769 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:171770 '*StructTraits*.*',
1771 '*TypeConverter*.*',
1772 ]
1773
scottmg7a6ed5ba2016-11-04 18:22:041774 # These third_party directories do not contain IPCs, but contain files
1775 # matching the above patterns, which trigger false positives.
1776 exclude_paths = [
1777 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291778 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041779 ]
1780
dchenge07de812016-06-20 19:27:171781 # Dictionary mapping an OWNERS file path to Patterns.
1782 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1783 # rules ) to a PatternEntry.
1784 # PatternEntry is a dictionary with two keys:
1785 # - 'files': the files that are matched by this pattern
1786 # - 'rules': the per-file rules needed for this pattern
1787 # For example, if we expect OWNERS file to contain rules for *.mojom and
1788 # *_struct_traits*.*, Patterns might look like this:
1789 # {
1790 # '*.mojom': {
1791 # 'files': ...,
1792 # 'rules': [
1793 # 'per-file *.mojom=set noparent',
1794 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1795 # ],
1796 # },
1797 # '*_struct_traits*.*': {
1798 # 'files': ...,
1799 # 'rules': [
1800 # 'per-file *_struct_traits*.*=set noparent',
1801 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1802 # ],
1803 # },
1804 # }
1805 to_check = {}
1806
Daniel Cheng13ca61a882017-08-25 15:11:251807 def AddPatternToCheck(input_file, pattern):
1808 owners_file = input_api.os_path.join(
1809 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1810 if owners_file not in to_check:
1811 to_check[owners_file] = {}
1812 if pattern not in to_check[owners_file]:
1813 to_check[owners_file][pattern] = {
1814 'files': [],
1815 'rules': [
1816 'per-file %s=set noparent' % pattern,
1817 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1818 ]
1819 }
Vaclav Brozekd5de76a2018-03-17 07:57:501820 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:251821
dchenge07de812016-06-20 19:27:171822 # Iterate through the affected files to see what we actually need to check
1823 # for. We should only nag patch authors about per-file rules if a file in that
1824 # directory would match that pattern. If a directory only contains *.mojom
1825 # files and no *_messages*.h files, we should only nag about rules for
1826 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251827 for f in input_api.AffectedFiles(include_deletes=False):
1828 # Manifest files don't have a strong naming convention. Instead, scan
1829 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161830 if (f.LocalPath().endswith('.json') and
1831 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1832 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251833 json_comment_eater = _ImportJSONCommentEater(input_api)
1834 mostly_json_lines = '\n'.join(f.NewContents())
1835 # Comments aren't allowed in strict JSON, so filter them out.
1836 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:431837 try:
1838 json_content = input_api.json.loads(json_lines)
1839 except:
1840 # There's another PRESUBMIT check that already verifies that JSON files
1841 # are not invalid, so no need to emit another warning here.
1842 continue
Daniel Cheng13ca61a882017-08-25 15:11:251843 if 'interface_provider_specs' in json_content:
1844 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171845 for pattern in file_patterns:
1846 if input_api.fnmatch.fnmatch(
1847 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041848 skip = False
1849 for exclude in exclude_paths:
1850 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1851 skip = True
1852 break
1853 if skip:
1854 continue
Daniel Cheng13ca61a882017-08-25 15:11:251855 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171856 break
1857
Daniel Cheng7052cdf2017-11-21 19:23:291858 return to_check
1859
1860
1861def _CheckIpcOwners(input_api, output_api):
1862 """Checks that affected files involving IPC have an IPC OWNERS rule."""
1863 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
1864
1865 if to_check:
1866 # If there are any OWNERS files to check, there are IPC-related changes in
1867 # this CL. Auto-CC the review list.
1868 output_api.AppendCC('[email protected]')
1869
1870 # Go through the OWNERS files to check, filtering out rules that are already
1871 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:171872 for owners_file, patterns in to_check.iteritems():
1873 try:
1874 with file(owners_file) as f:
1875 lines = set(f.read().splitlines())
1876 for entry in patterns.itervalues():
1877 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1878 ]
1879 except IOError:
1880 # No OWNERS file, so all the rules are definitely missing.
1881 continue
1882
1883 # All the remaining lines weren't found in OWNERS files, so emit an error.
1884 errors = []
1885 for owners_file, patterns in to_check.iteritems():
1886 missing_lines = []
1887 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:501888 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:171889 missing_lines.extend(entry['rules'])
1890 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1891 if missing_lines:
1892 errors.append(
Daniel Cheng52111692017-06-14 08:00:591893 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171894 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1895
1896 results = []
1897 if errors:
vabrf5ce3bf92016-07-11 14:52:411898 if input_api.is_committing:
1899 output = output_api.PresubmitError
1900 else:
1901 output = output_api.PresubmitPromptWarning
1902 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591903 'Found OWNERS files that need to be updated for IPC security ' +
1904 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171905 long_text='\n\n'.join(errors)))
1906
1907 return results
1908
1909
jbriance9e12f162016-11-25 07:57:501910def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311911 """Checks that added or removed lines in non third party affected
1912 header files do not lead to new useless class or struct forward
1913 declaration.
jbriance9e12f162016-11-25 07:57:501914 """
1915 results = []
1916 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1917 input_api.re.MULTILINE)
1918 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1919 input_api.re.MULTILINE)
1920 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311921 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191922 not f.LocalPath().startswith('third_party/blink') and
1923 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311924 not f.LocalPath().startswith('third_party/WebKit') and
1925 not f.LocalPath().startswith('third_party\\WebKit')):
1926 continue
1927
jbriance9e12f162016-11-25 07:57:501928 if not f.LocalPath().endswith('.h'):
1929 continue
1930
1931 contents = input_api.ReadFile(f)
1932 fwd_decls = input_api.re.findall(class_pattern, contents)
1933 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1934
1935 useless_fwd_decls = []
1936 for decl in fwd_decls:
1937 count = sum(1 for _ in input_api.re.finditer(
1938 r'\b%s\b' % input_api.re.escape(decl), contents))
1939 if count == 1:
1940 useless_fwd_decls.append(decl)
1941
1942 if not useless_fwd_decls:
1943 continue
1944
1945 for line in f.GenerateScmDiff().splitlines():
1946 if (line.startswith('-') and not line.startswith('--') or
1947 line.startswith('+') and not line.startswith('++')):
1948 for decl in useless_fwd_decls:
1949 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1950 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241951 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501952 (f.LocalPath(), decl)))
1953 useless_fwd_decls.remove(decl)
1954
1955 return results
1956
1957
dskiba88634f4e2015-08-14 23:03:291958def _CheckAndroidToastUsage(input_api, output_api):
1959 """Checks that code uses org.chromium.ui.widget.Toast instead of
1960 android.widget.Toast (Chromium Toast doesn't force hardware
1961 acceleration on low-end devices, saving memory).
1962 """
1963 toast_import_pattern = input_api.re.compile(
1964 r'^import android\.widget\.Toast;$')
1965
1966 errors = []
1967
1968 sources = lambda affected_file: input_api.FilterSourceFile(
1969 affected_file,
1970 black_list=(_EXCLUDED_PATHS +
1971 _TEST_CODE_EXCLUDED_PATHS +
1972 input_api.DEFAULT_BLACK_LIST +
1973 (r'^chromecast[\\\/].*',
1974 r'^remoting[\\\/].*')),
1975 white_list=(r'.*\.java$',))
1976
1977 for f in input_api.AffectedSourceFiles(sources):
1978 for line_num, line in f.ChangedContents():
1979 if toast_import_pattern.search(line):
1980 errors.append("%s:%d" % (f.LocalPath(), line_num))
1981
1982 results = []
1983
1984 if errors:
1985 results.append(output_api.PresubmitError(
1986 'android.widget.Toast usage is detected. Android toasts use hardware'
1987 ' acceleration, and can be\ncostly on low-end devices. Please use'
1988 ' org.chromium.ui.widget.Toast instead.\n'
1989 'Contact [email protected] if you have any questions.',
1990 errors))
1991
1992 return results
1993
1994
dgnaa68d5e2015-06-10 10:08:221995def _CheckAndroidCrLogUsage(input_api, output_api):
1996 """Checks that new logs using org.chromium.base.Log:
1997 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511998 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221999 """
pkotwicza1dd0b002016-05-16 14:41:042000
torne89540622017-03-24 19:41:302001 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:042002 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:302003 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:042004 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:302005 # WebView license viewer code cannot depend on //base; used in stub APK.
2006 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
2007 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:042008 ]
2009
dgnaa68d5e2015-06-10 10:08:222010 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:122011 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
2012 class_in_base_pattern = input_api.re.compile(
2013 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
2014 has_some_log_import_pattern = input_api.re.compile(
2015 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222016 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:122017 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:222018 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:512019 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:222020 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222021
Vincent Scheib16d7b272015-09-15 18:09:072022 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:222023 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:042024 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
2025 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:122026
dgnaa68d5e2015-06-10 10:08:222027 tag_decl_errors = []
2028 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:122029 tag_errors = []
dgn38736db2015-09-18 19:20:512030 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:122031 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:222032
2033 for f in input_api.AffectedSourceFiles(sources):
2034 file_content = input_api.ReadFile(f)
2035 has_modified_logs = False
2036
2037 # Per line checks
dgn87d9fb62015-06-12 09:15:122038 if (cr_log_import_pattern.search(file_content) or
2039 (class_in_base_pattern.search(file_content) and
2040 not has_some_log_import_pattern.search(file_content))):
2041 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:222042 for line_num, line in f.ChangedContents():
2043
2044 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:122045 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:222046 if match:
2047 has_modified_logs = True
2048
2049 # Make sure it uses "TAG"
2050 if not match.group('tag') == 'TAG':
2051 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:122052 else:
2053 # Report non cr Log function calls in changed lines
2054 for line_num, line in f.ChangedContents():
2055 if log_call_pattern.search(line):
2056 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:222057
2058 # Per file checks
2059 if has_modified_logs:
2060 # Make sure the tag is using the "cr" prefix and is not too long
2061 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:512062 tag_name = match.group('name') if match else None
2063 if not tag_name:
dgnaa68d5e2015-06-10 10:08:222064 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512065 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:222066 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512067 elif '.' in tag_name:
2068 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:222069
2070 results = []
2071 if tag_decl_errors:
2072 results.append(output_api.PresubmitPromptWarning(
2073 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:512074 '"private static final String TAG = "<package tag>".\n'
2075 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222076 tag_decl_errors))
2077
2078 if tag_length_errors:
2079 results.append(output_api.PresubmitError(
2080 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:512081 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222082 tag_length_errors))
2083
2084 if tag_errors:
2085 results.append(output_api.PresubmitPromptWarning(
2086 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
2087 tag_errors))
2088
dgn87d9fb62015-06-12 09:15:122089 if util_log_errors:
dgn4401aa52015-04-29 16:26:172090 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:122091 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
2092 util_log_errors))
2093
dgn38736db2015-09-18 19:20:512094 if tag_with_dot_errors:
2095 results.append(output_api.PresubmitPromptWarning(
2096 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
2097 tag_with_dot_errors))
2098
dgn4401aa52015-04-29 16:26:172099 return results
2100
2101
Yoland Yanb92fa522017-08-28 17:37:062102def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
2103 """Checks that junit.framework.* is no longer used."""
2104 deprecated_junit_framework_pattern = input_api.re.compile(
2105 r'^import junit\.framework\..*;',
2106 input_api.re.MULTILINE)
2107 sources = lambda x: input_api.FilterSourceFile(
2108 x, white_list=(r'.*\.java$',), black_list=None)
2109 errors = []
2110 for f in input_api.AffectedFiles(sources):
2111 for line_num, line in f.ChangedContents():
2112 if deprecated_junit_framework_pattern.search(line):
2113 errors.append("%s:%d" % (f.LocalPath(), line_num))
2114
2115 results = []
2116 if errors:
2117 results.append(output_api.PresubmitError(
2118 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
2119 '(org.junit.*) from //third_party/junit. Contact [email protected]'
2120 ' if you have any question.', errors))
2121 return results
2122
2123
2124def _CheckAndroidTestJUnitInheritance(input_api, output_api):
2125 """Checks that if new Java test classes have inheritance.
2126 Either the new test class is JUnit3 test or it is a JUnit4 test class
2127 with a base class, either case is undesirable.
2128 """
2129 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
2130
2131 sources = lambda x: input_api.FilterSourceFile(
2132 x, white_list=(r'.*Test\.java$',), black_list=None)
2133 errors = []
2134 for f in input_api.AffectedFiles(sources):
2135 if not f.OldContents():
2136 class_declaration_start_flag = False
2137 for line_num, line in f.ChangedContents():
2138 if class_declaration_pattern.search(line):
2139 class_declaration_start_flag = True
2140 if class_declaration_start_flag and ' extends ' in line:
2141 errors.append('%s:%d' % (f.LocalPath(), line_num))
2142 if '{' in line:
2143 class_declaration_start_flag = False
2144
2145 results = []
2146 if errors:
2147 results.append(output_api.PresubmitPromptWarning(
2148 'The newly created files include Test classes that inherits from base'
2149 ' class. Please do not use inheritance in JUnit4 tests or add new'
2150 ' JUnit3 tests. Contact [email protected] if you have any'
2151 ' questions.', errors))
2152 return results
2153
yolandyan45001472016-12-21 21:12:422154def _CheckAndroidTestAnnotationUsage(input_api, output_api):
2155 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
2156 deprecated_annotation_import_pattern = input_api.re.compile(
2157 r'^import android\.test\.suitebuilder\.annotation\..*;',
2158 input_api.re.MULTILINE)
2159 sources = lambda x: input_api.FilterSourceFile(
2160 x, white_list=(r'.*\.java$',), black_list=None)
2161 errors = []
2162 for f in input_api.AffectedFiles(sources):
2163 for line_num, line in f.ChangedContents():
2164 if deprecated_annotation_import_pattern.search(line):
2165 errors.append("%s:%d" % (f.LocalPath(), line_num))
2166
2167 results = []
2168 if errors:
2169 results.append(output_api.PresubmitError(
2170 'Annotations in android.test.suitebuilder.annotation have been'
2171 ' deprecated since API level 24. Please use android.support.test.filters'
2172 ' from //third_party/android_support_test_runner:runner_java instead.'
2173 ' Contact [email protected] if you have any questions.', errors))
2174 return results
2175
2176
agrieve7b6479d82015-10-07 14:24:222177def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
2178 """Checks if MDPI assets are placed in a correct directory."""
2179 file_filter = lambda f: (f.LocalPath().endswith('.png') and
2180 ('/res/drawable/' in f.LocalPath() or
2181 '/res/drawable-ldrtl/' in f.LocalPath()))
2182 errors = []
2183 for f in input_api.AffectedFiles(include_deletes=False,
2184 file_filter=file_filter):
2185 errors.append(' %s' % f.LocalPath())
2186
2187 results = []
2188 if errors:
2189 results.append(output_api.PresubmitError(
2190 'MDPI assets should be placed in /res/drawable-mdpi/ or '
2191 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
2192 '/res/drawable-ldrtl/.\n'
2193 'Contact [email protected] if you have questions.', errors))
2194 return results
2195
2196
Nate Fischer535972b2017-09-16 01:06:182197def _CheckAndroidWebkitImports(input_api, output_api):
2198 """Checks that code uses org.chromium.base.Callback instead of
2199 android.widget.ValueCallback except in the WebView glue layer.
2200 """
2201 valuecallback_import_pattern = input_api.re.compile(
2202 r'^import android\.webkit\.ValueCallback;$')
2203
2204 errors = []
2205
2206 sources = lambda affected_file: input_api.FilterSourceFile(
2207 affected_file,
2208 black_list=(_EXCLUDED_PATHS +
2209 _TEST_CODE_EXCLUDED_PATHS +
2210 input_api.DEFAULT_BLACK_LIST +
2211 (r'^android_webview[\\\/]glue[\\\/].*',)),
2212 white_list=(r'.*\.java$',))
2213
2214 for f in input_api.AffectedSourceFiles(sources):
2215 for line_num, line in f.ChangedContents():
2216 if valuecallback_import_pattern.search(line):
2217 errors.append("%s:%d" % (f.LocalPath(), line_num))
2218
2219 results = []
2220
2221 if errors:
2222 results.append(output_api.PresubmitError(
2223 'android.webkit.ValueCallback usage is detected outside of the glue'
2224 ' layer. To stay compatible with the support library, android.webkit.*'
2225 ' classes should only be used inside the glue layer and'
2226 ' org.chromium.base.Callback should be used instead.',
2227 errors))
2228
2229 return results
2230
2231
agrievef32bcc72016-04-04 14:57:402232class PydepsChecker(object):
2233 def __init__(self, input_api, pydeps_files):
2234 self._file_cache = {}
2235 self._input_api = input_api
2236 self._pydeps_files = pydeps_files
2237
2238 def _LoadFile(self, path):
2239 """Returns the list of paths within a .pydeps file relative to //."""
2240 if path not in self._file_cache:
2241 with open(path) as f:
2242 self._file_cache[path] = f.read()
2243 return self._file_cache[path]
2244
2245 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
2246 """Returns an interable of paths within the .pydep, relativized to //."""
2247 os_path = self._input_api.os_path
2248 pydeps_dir = os_path.dirname(pydeps_path)
2249 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2250 if not l.startswith('*'))
2251 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2252
2253 def _CreateFilesToPydepsMap(self):
2254 """Returns a map of local_path -> list_of_pydeps."""
2255 ret = {}
2256 for pydep_local_path in self._pydeps_files:
2257 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2258 ret.setdefault(path, []).append(pydep_local_path)
2259 return ret
2260
2261 def ComputeAffectedPydeps(self):
2262 """Returns an iterable of .pydeps files that might need regenerating."""
2263 affected_pydeps = set()
2264 file_to_pydeps_map = None
2265 for f in self._input_api.AffectedFiles(include_deletes=True):
2266 local_path = f.LocalPath()
2267 if local_path == 'DEPS':
2268 return self._pydeps_files
2269 elif local_path.endswith('.pydeps'):
2270 if local_path in self._pydeps_files:
2271 affected_pydeps.add(local_path)
2272 elif local_path.endswith('.py'):
2273 if file_to_pydeps_map is None:
2274 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2275 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2276 return affected_pydeps
2277
2278 def DetermineIfStale(self, pydeps_path):
2279 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412280 import difflib
John Budorick47ca3fe2018-02-10 00:53:102281 import os
2282
agrievef32bcc72016-04-04 14:57:402283 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2284 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:102285 env = dict(os.environ)
2286 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:402287 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:102288 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412289 old_contents = old_pydeps_data[2:]
2290 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402291 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412292 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402293
2294
2295def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2296 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:402297 # This check is for Python dependency lists (.pydeps files), and involves
2298 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
2299 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:282300 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002301 return []
Mostyn Bramley-Moore6b427322017-12-21 22:11:022302 # TODO(agrieve): Update when there's a better way to detect
2303 # this: crbug.com/570091
agrievef32bcc72016-04-04 14:57:402304 is_android = input_api.os_path.exists('third_party/android_tools')
2305 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2306 results = []
2307 # First, check for new / deleted .pydeps.
2308 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:032309 # Check whether we are running the presubmit check for a file in src.
2310 # f.LocalPath is relative to repo (src, or internal repo).
2311 # os_path.exists is relative to src repo.
2312 # Therefore if os_path.exists is true, it means f.LocalPath is relative
2313 # to src and we can conclude that the pydeps is in src.
2314 if input_api.os_path.exists(f.LocalPath()):
2315 if f.LocalPath().endswith('.pydeps'):
2316 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2317 results.append(output_api.PresubmitError(
2318 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2319 'remove %s' % f.LocalPath()))
2320 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2321 results.append(output_api.PresubmitError(
2322 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2323 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:402324
2325 if results:
2326 return results
2327
2328 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2329
2330 for pydep_path in checker.ComputeAffectedPydeps():
2331 try:
phajdan.jr0d9878552016-11-04 10:49:412332 result = checker.DetermineIfStale(pydep_path)
2333 if result:
2334 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402335 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412336 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2337 'To regenerate, run:\n\n %s' %
2338 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402339 except input_api.subprocess.CalledProcessError as error:
2340 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2341 long_text=error.output)]
2342
2343 return results
2344
2345
glidere61efad2015-02-18 17:39:432346def _CheckSingletonInHeaders(input_api, output_api):
2347 """Checks to make sure no header files have |Singleton<|."""
2348 def FileFilter(affected_file):
2349 # It's ok for base/memory/singleton.h to have |Singleton<|.
2350 black_list = (_EXCLUDED_PATHS +
2351 input_api.DEFAULT_BLACK_LIST +
Michael Warrese4451492018-03-07 04:42:472352 (r"^base[\\\/]memory[\\\/]singleton\.h$",
2353 r"^net[\\\/]quic[\\\/]platform[\\\/]impl[\\\/]"
2354 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:432355 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2356
sergeyu34d21222015-09-16 00:11:442357 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432358 files = []
2359 for f in input_api.AffectedSourceFiles(FileFilter):
2360 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2361 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2362 contents = input_api.ReadFile(f)
2363 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242364 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432365 pattern.search(line)):
2366 files.append(f)
2367 break
2368
2369 if files:
yolandyandaabc6d2016-04-18 18:29:392370 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442371 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432372 'Please move them to an appropriate source file so that the ' +
2373 'template gets instantiated in a single compilation unit.',
2374 files) ]
2375 return []
2376
2377
[email protected]fd20b902014-05-09 02:14:532378_DEPRECATED_CSS = [
2379 # Values
2380 ( "-webkit-box", "flex" ),
2381 ( "-webkit-inline-box", "inline-flex" ),
2382 ( "-webkit-flex", "flex" ),
2383 ( "-webkit-inline-flex", "inline-flex" ),
2384 ( "-webkit-min-content", "min-content" ),
2385 ( "-webkit-max-content", "max-content" ),
2386
2387 # Properties
2388 ( "-webkit-background-clip", "background-clip" ),
2389 ( "-webkit-background-origin", "background-origin" ),
2390 ( "-webkit-background-size", "background-size" ),
2391 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442392 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532393
2394 # Functions
2395 ( "-webkit-gradient", "gradient" ),
2396 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2397 ( "-webkit-linear-gradient", "linear-gradient" ),
2398 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2399 ( "-webkit-radial-gradient", "radial-gradient" ),
2400 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2401]
2402
dbeam1ec68ac2016-12-15 05:22:242403def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532404 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252405 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342406 documentation and iOS CSS for dom distiller
2407 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252408 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532409 results = []
dbeam070cfe62014-10-22 06:44:022410 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252411 black_list = (_EXCLUDED_PATHS +
2412 _TEST_CODE_EXCLUDED_PATHS +
2413 input_api.DEFAULT_BLACK_LIST +
2414 (r"^chrome/common/extensions/docs",
2415 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342416 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442417 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252418 r"^native_client_sdk"))
2419 file_filter = lambda f: input_api.FilterSourceFile(
2420 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532421 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2422 for line_num, line in fpath.ChangedContents():
2423 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022424 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532425 results.append(output_api.PresubmitError(
2426 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2427 (fpath.LocalPath(), line_num, deprecated_value, value)))
2428 return results
2429
mohan.reddyf21db962014-10-16 12:26:472430
dbeam070cfe62014-10-22 06:44:022431_DEPRECATED_JS = [
2432 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2433 ( "__defineGetter__", "Object.defineProperty" ),
2434 ( "__defineSetter__", "Object.defineProperty" ),
2435]
2436
dbeam1ec68ac2016-12-15 05:22:242437def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022438 """Make sure that we don't use deprecated JS in Chrome code."""
2439 results = []
2440 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2441 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2442 input_api.DEFAULT_BLACK_LIST)
2443 file_filter = lambda f: input_api.FilterSourceFile(
2444 f, white_list=file_inclusion_pattern, black_list=black_list)
2445 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2446 for lnum, line in fpath.ChangedContents():
2447 for (deprecated, replacement) in _DEPRECATED_JS:
2448 if deprecated in line:
2449 results.append(output_api.PresubmitError(
2450 "%s:%d: Use of deprecated JS %s, use %s instead" %
2451 (fpath.LocalPath(), lnum, deprecated, replacement)))
2452 return results
2453
dpapadd651231d82017-07-21 02:44:472454def _CheckForRiskyJsArrowFunction(line_number, line):
2455 if ' => ' in line:
2456 return "line %d, is using an => (arrow) function\n %s\n" % (
2457 line_number, line)
2458 return ''
2459
2460def _CheckForRiskyJsConstLet(input_api, line_number, line):
2461 if input_api.re.match('^\s*(const|let)\s', line):
2462 return "line %d, is using const/let keyword\n %s\n" % (
2463 line_number, line)
2464 return ''
dbeam070cfe62014-10-22 06:44:022465
dbeam1ec68ac2016-12-15 05:22:242466def _CheckForRiskyJsFeatures(input_api, output_api):
2467 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002468 # 'ui/webui/resources/cr_components are not allowed on ios'
2469 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572470 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002471 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472472 results = []
dbeam1ec68ac2016-12-15 05:22:242473 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472474 arrow_error_lines = []
2475 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242476 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472477 arrow_error_lines += filter(None, [
2478 _CheckForRiskyJsArrowFunction(lnum, line),
2479 ])
dbeam1ec68ac2016-12-15 05:22:242480
dpapadd651231d82017-07-21 02:44:472481 const_let_error_lines += filter(None, [
2482 _CheckForRiskyJsConstLet(input_api, lnum, line),
2483 ])
dbeam1ec68ac2016-12-15 05:22:242484
dpapadd651231d82017-07-21 02:44:472485 if arrow_error_lines:
2486 arrow_error_lines = map(
2487 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2488 results.append(
2489 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2490"""
2491Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242492%s
2493Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2494https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472495""" % f.LocalPath()
2496 ])))
dbeam1ec68ac2016-12-15 05:22:242497
dpapadd651231d82017-07-21 02:44:472498 if const_let_error_lines:
2499 const_let_error_lines = map(
2500 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2501 results.append(
2502 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2503"""
2504Use of const/let keywords detected in:
2505%s
2506Please ensure your code does not run on iOS9 because const/let is not fully
2507supported.
2508https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2509https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2510""" % f.LocalPath()
2511 ])))
2512
2513 return results
dbeam1ec68ac2016-12-15 05:22:242514
rlanday6802cf632017-05-30 17:48:362515def _CheckForRelativeIncludes(input_api, output_api):
2516 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2517 import sys
2518 original_sys_path = sys.path
2519 try:
2520 sys.path = sys.path + [input_api.os_path.join(
2521 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2522 from cpp_checker import CppChecker
2523 finally:
2524 # Restore sys.path to what it was before.
2525 sys.path = original_sys_path
2526
2527 bad_files = {}
2528 for f in input_api.AffectedFiles(include_deletes=False):
2529 if (f.LocalPath().startswith('third_party') and
2530 not f.LocalPath().startswith('third_party/WebKit') and
2531 not f.LocalPath().startswith('third_party\\WebKit')):
2532 continue
2533
2534 if not CppChecker.IsCppFile(f.LocalPath()):
2535 continue
2536
Vaclav Brozekd5de76a2018-03-17 07:57:502537 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:362538 if "#include" in line and "../" in line]
2539 if not relative_includes:
2540 continue
2541 bad_files[f.LocalPath()] = relative_includes
2542
2543 if not bad_files:
2544 return []
2545
2546 error_descriptions = []
2547 for file_path, bad_lines in bad_files.iteritems():
2548 error_description = file_path
2549 for line in bad_lines:
2550 error_description += '\n ' + line
2551 error_descriptions.append(error_description)
2552
2553 results = []
2554 results.append(output_api.PresubmitError(
2555 'You added one or more relative #include paths (including "../").\n'
2556 'These shouldn\'t be used because they can be used to include headers\n'
2557 'from code that\'s not correctly specified as a dependency in the\n'
2558 'relevant BUILD.gn file(s).',
2559 error_descriptions))
2560
2561 return results
2562
Takeshi Yoshinoe387aa32017-08-02 13:16:132563
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202564def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2565 if not isinstance(key, ast.Str):
2566 return 'Key at line %d must be a string literal' % key.lineno
2567 if not isinstance(value, ast.Dict):
2568 return 'Value at line %d must be a dict' % value.lineno
2569 if len(value.keys) != 1:
2570 return 'Dict at line %d must have single entry' % value.lineno
2571 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2572 return (
2573 'Entry at line %d must have a string literal \'filepath\' as key' %
2574 value.lineno)
2575 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132576
Takeshi Yoshinoe387aa32017-08-02 13:16:132577
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202578def _CheckWatchlistsEntrySyntax(key, value, ast):
2579 if not isinstance(key, ast.Str):
2580 return 'Key at line %d must be a string literal' % key.lineno
2581 if not isinstance(value, ast.List):
2582 return 'Value at line %d must be a list' % value.lineno
2583 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132584
Takeshi Yoshinoe387aa32017-08-02 13:16:132585
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202586def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2587 mismatch_template = (
2588 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2589 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132590
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202591 i = 0
2592 last_key = ''
2593 while True:
2594 if i >= len(wd_dict.keys):
2595 if i >= len(w_dict.keys):
2596 return None
2597 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2598 elif i >= len(w_dict.keys):
2599 return (
2600 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132601
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202602 wd_key = wd_dict.keys[i]
2603 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132604
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202605 result = _CheckWatchlistDefinitionsEntrySyntax(
2606 wd_key, wd_dict.values[i], ast)
2607 if result is not None:
2608 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132609
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202610 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2611 if result is not None:
2612 return 'Bad entry in WATCHLISTS dict: %s' % result
2613
2614 if wd_key.s != w_key.s:
2615 return mismatch_template % (
2616 '%s at line %d' % (wd_key.s, wd_key.lineno),
2617 '%s at line %d' % (w_key.s, w_key.lineno))
2618
2619 if wd_key.s < last_key:
2620 return (
2621 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2622 (wd_key.lineno, w_key.lineno))
2623 last_key = wd_key.s
2624
2625 i = i + 1
2626
2627
2628def _CheckWATCHLISTSSyntax(expression, ast):
2629 if not isinstance(expression, ast.Expression):
2630 return 'WATCHLISTS file must contain a valid expression'
2631 dictionary = expression.body
2632 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2633 return 'WATCHLISTS file must have single dict with exactly two entries'
2634
2635 first_key = dictionary.keys[0]
2636 first_value = dictionary.values[0]
2637 second_key = dictionary.keys[1]
2638 second_value = dictionary.values[1]
2639
2640 if (not isinstance(first_key, ast.Str) or
2641 first_key.s != 'WATCHLIST_DEFINITIONS' or
2642 not isinstance(first_value, ast.Dict)):
2643 return (
2644 'The first entry of the dict in WATCHLISTS file must be '
2645 'WATCHLIST_DEFINITIONS dict')
2646
2647 if (not isinstance(second_key, ast.Str) or
2648 second_key.s != 'WATCHLISTS' or
2649 not isinstance(second_value, ast.Dict)):
2650 return (
2651 'The second entry of the dict in WATCHLISTS file must be '
2652 'WATCHLISTS dict')
2653
2654 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132655
2656
2657def _CheckWATCHLISTS(input_api, output_api):
2658 for f in input_api.AffectedFiles(include_deletes=False):
2659 if f.LocalPath() == 'WATCHLISTS':
2660 contents = input_api.ReadFile(f, 'r')
2661
2662 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202663 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132664 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202665 # Get an AST tree for it and scan the tree for detailed style checking.
2666 expression = input_api.ast.parse(
2667 contents, filename='WATCHLISTS', mode='eval')
2668 except ValueError as e:
2669 return [output_api.PresubmitError(
2670 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2671 except SyntaxError as e:
2672 return [output_api.PresubmitError(
2673 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2674 except TypeError as e:
2675 return [output_api.PresubmitError(
2676 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132677
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202678 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2679 if result is not None:
2680 return [output_api.PresubmitError(result)]
2681 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132682
2683 return []
2684
2685
dgnaa68d5e2015-06-10 10:08:222686def _AndroidSpecificOnUploadChecks(input_api, output_api):
2687 """Groups checks that target android code."""
2688 results = []
dgnaa68d5e2015-06-10 10:08:222689 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222690 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292691 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062692 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2693 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422694 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182695 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222696 return results
2697
2698
[email protected]22c9bd72011-03-27 16:47:392699def _CommonChecks(input_api, output_api):
2700 """Checks common to both upload and commit."""
2701 results = []
2702 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382703 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542704 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:082705
2706 author = input_api.change.author_email
2707 if author and author not in _KNOWN_ROBOTS:
2708 results.extend(
2709 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
2710
[email protected]55459852011-08-10 15:17:192711 results.extend(
[email protected]760deea2013-12-10 19:33:492712 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:232713 results.extend(
2714 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542715 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182716 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522717 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222718 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442719 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592720 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062721 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122722 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182723 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222724 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302725 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492726 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032727 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492728 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442729 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272730 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072731 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542732 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442733 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392734 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552735 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042736 results.extend(
2737 input_api.canned_checks.CheckChangeHasNoTabs(
2738 input_api,
2739 output_api,
2740 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402741 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162742 results.extend(_CheckForAnonymousVariables(input_api, output_api))
Peter Kasting4844e46e2018-02-23 07:27:102743 results.extend(_CheckUniquePtr(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082744 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242745 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2746 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472747 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042748 results.extend(_CheckForIPCRules(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:142749 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232750 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432751 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402752 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152753 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172754 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502755 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242756 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362757 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132758 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432759 results.extend(input_api.RunTests(
2760 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242761
Vaclav Brozekcdc7defb2018-03-20 09:54:352762 for f in input_api.AffectedFiles():
2763 path, name = input_api.os_path.split(f.LocalPath())
2764 if name == 'PRESUBMIT.py':
2765 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
2766 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2767 input_api, output_api, full_path,
2768 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392769 return results
[email protected]1f7b4172010-01-28 01:17:342770
[email protected]b337cb5b2011-01-23 21:24:052771
[email protected]b8079ae4a2012-12-05 19:56:492772def _CheckPatchFiles(input_api, output_api):
2773 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2774 if f.LocalPath().endswith(('.orig', '.rej'))]
2775 if problems:
2776 return [output_api.PresubmitError(
2777 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032778 else:
2779 return []
[email protected]b8079ae4a2012-12-05 19:56:492780
2781
Kent Tamura5a8755d2017-06-29 23:37:072782def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212783 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2784 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2785 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072786 include_re = input_api.re.compile(
2787 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2788 extension_re = input_api.re.compile(r'\.[a-z]+$')
2789 errors = []
2790 for f in input_api.AffectedFiles():
2791 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2792 continue
2793 found_line_number = None
2794 found_macro = None
2795 for line_num, line in f.ChangedContents():
2796 match = macro_re.search(line)
2797 if match:
2798 found_line_number = line_num
2799 found_macro = match.group(2)
2800 break
2801 if not found_line_number:
2802 continue
2803
2804 found_include = False
2805 for line in f.NewContents():
2806 if include_re.search(line):
2807 found_include = True
2808 break
2809 if found_include:
2810 continue
2811
2812 if not f.LocalPath().endswith('.h'):
2813 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2814 try:
2815 content = input_api.ReadFile(primary_header_path, 'r')
2816 if include_re.search(content):
2817 continue
2818 except IOError:
2819 pass
2820 errors.append('%s:%d %s macro is used without including build/'
2821 'build_config.h.'
2822 % (f.LocalPath(), found_line_number, found_macro))
2823 if errors:
2824 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2825 return []
2826
2827
[email protected]b00342e7f2013-03-26 16:21:542828def _DidYouMeanOSMacro(bad_macro):
2829 try:
2830 return {'A': 'OS_ANDROID',
2831 'B': 'OS_BSD',
2832 'C': 'OS_CHROMEOS',
2833 'F': 'OS_FREEBSD',
2834 'L': 'OS_LINUX',
2835 'M': 'OS_MACOSX',
2836 'N': 'OS_NACL',
2837 'O': 'OS_OPENBSD',
2838 'P': 'OS_POSIX',
2839 'S': 'OS_SOLARIS',
2840 'W': 'OS_WIN'}[bad_macro[3].upper()]
2841 except KeyError:
2842 return ''
2843
2844
2845def _CheckForInvalidOSMacrosInFile(input_api, f):
2846 """Check for sensible looking, totally invalid OS macros."""
2847 preprocessor_statement = input_api.re.compile(r'^\s*#')
2848 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2849 results = []
2850 for lnum, line in f.ChangedContents():
2851 if preprocessor_statement.search(line):
2852 for match in os_macro.finditer(line):
2853 if not match.group(1) in _VALID_OS_MACROS:
2854 good = _DidYouMeanOSMacro(match.group(1))
2855 did_you_mean = ' (did you mean %s?)' % good if good else ''
2856 results.append(' %s:%d %s%s' % (f.LocalPath(),
2857 lnum,
2858 match.group(1),
2859 did_you_mean))
2860 return results
2861
2862
2863def _CheckForInvalidOSMacros(input_api, output_api):
2864 """Check all affected files for invalid OS macros."""
2865 bad_macros = []
2866 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472867 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542868 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2869
2870 if not bad_macros:
2871 return []
2872
2873 return [output_api.PresubmitError(
2874 'Possibly invalid OS macro[s] found. Please fix your code\n'
2875 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2876
lliabraa35bab3932014-10-01 12:16:442877
2878def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2879 """Check all affected files for invalid "if defined" macros."""
2880 ALWAYS_DEFINED_MACROS = (
2881 "TARGET_CPU_PPC",
2882 "TARGET_CPU_PPC64",
2883 "TARGET_CPU_68K",
2884 "TARGET_CPU_X86",
2885 "TARGET_CPU_ARM",
2886 "TARGET_CPU_MIPS",
2887 "TARGET_CPU_SPARC",
2888 "TARGET_CPU_ALPHA",
2889 "TARGET_IPHONE_SIMULATOR",
2890 "TARGET_OS_EMBEDDED",
2891 "TARGET_OS_IPHONE",
2892 "TARGET_OS_MAC",
2893 "TARGET_OS_UNIX",
2894 "TARGET_OS_WIN32",
2895 )
2896 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2897 results = []
2898 for lnum, line in f.ChangedContents():
2899 for match in ifdef_macro.finditer(line):
2900 if match.group(1) in ALWAYS_DEFINED_MACROS:
2901 always_defined = ' %s is always defined. ' % match.group(1)
2902 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2903 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2904 lnum,
2905 always_defined,
2906 did_you_mean))
2907 return results
2908
2909
2910def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2911 """Check all affected files for invalid "if defined" macros."""
2912 bad_macros = []
2913 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212914 if f.LocalPath().startswith('third_party/sqlite/'):
2915 continue
lliabraa35bab3932014-10-01 12:16:442916 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2917 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2918
2919 if not bad_macros:
2920 return []
2921
2922 return [output_api.PresubmitError(
2923 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2924 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2925 bad_macros)]
2926
2927
mlamouria82272622014-09-16 18:45:042928def _CheckForIPCRules(input_api, output_api):
2929 """Check for same IPC rules described in
2930 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2931 """
2932 base_pattern = r'IPC_ENUM_TRAITS\('
2933 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2934 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2935
2936 problems = []
2937 for f in input_api.AffectedSourceFiles(None):
2938 local_path = f.LocalPath()
2939 if not local_path.endswith('.h'):
2940 continue
2941 for line_number, line in f.ChangedContents():
2942 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2943 problems.append(
2944 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2945
2946 if problems:
2947 return [output_api.PresubmitPromptWarning(
2948 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2949 else:
2950 return []
2951
[email protected]b00342e7f2013-03-26 16:21:542952
Daniel Bratell8ba52722018-03-02 16:06:142953def _CheckForIncludeGuards(input_api, output_api):
2954 """Check that header files have proper guards against multiple inclusion.
2955 If a file should not have such guards (and it probably should) then it
2956 should include the string "no-include-guard-because-multiply-included".
2957 """
2958 def is_header_file(f):
2959 return f.LocalPath().endswith('.h')
2960
2961 def replace_special_with_underscore(string):
2962 return input_api.re.sub(r'[\\/.-]', '_', string)
2963
2964 errors = []
2965
2966 for f in input_api.AffectedSourceFiles(is_header_file):
2967 guard_name = None
2968 guard_line_number = None
2969 seen_guard_end = False
2970
2971 file_with_path = input_api.os_path.normpath(f.LocalPath())
2972 base_file_name = input_api.os_path.splitext(
2973 input_api.os_path.basename(file_with_path))[0]
2974 upper_base_file_name = base_file_name.upper()
2975
2976 expected_guard = replace_special_with_underscore(
2977 file_with_path.upper() + '_')
2978 expected_guard_if_blink = base_file_name + '_h'
2979
2980 # For "path/elem/file_name.h" we should really only accept
2981 # PATH_ELEM_FILE_NAME_H_ per coding style or, if Blink,
2982 # file_name_h. Unfortunately there are too many (1000+) files
2983 # with slight deviations from the coding style. Since the most
2984 # important part is that the include guard is there, and that it's
2985 # unique, not the name, this check is forgiving for existing files.
2986 #
2987 # As code becomes more uniform, this could be made stricter.
2988
2989 guard_name_pattern_list = [
2990 # Anything with the right suffix (maybe with an extra _).
2991 r'\w+_H__?',
2992
2993 # To cover include guards with Blink style.
2994 r'\w+_h',
2995
2996 # Anything including the uppercase name of the file.
2997 r'\w*' + input_api.re.escape(replace_special_with_underscore(
2998 upper_base_file_name)) + r'\w*',
2999 ]
3000 guard_name_pattern = '|'.join(guard_name_pattern_list)
3001 guard_pattern = input_api.re.compile(
3002 r'#ifndef\s+(' + guard_name_pattern + ')')
3003
3004 for line_number, line in enumerate(f.NewContents()):
3005 if 'no-include-guard-because-multiply-included' in line:
3006 guard_name = 'DUMMY' # To not trigger check outside the loop.
3007 break
3008
3009 if guard_name is None:
3010 match = guard_pattern.match(line)
3011 if match:
3012 guard_name = match.group(1)
3013 guard_line_number = line_number
3014
3015 # We allow existing files to use slightly wrong include
3016 # guards, but new files should get it right.
3017 if not f.OldContents():
3018 is_in_blink = file_with_path.startswith(input_api.os_path.join(
3019 'third_party', 'WebKit'))
3020 if not (guard_name == expected_guard or
3021 is_in_blink and guard_name == expected_guard_if_blink):
3022 if is_in_blink:
3023 expected_text = "%s or %s" % (expected_guard,
3024 expected_guard_if_blink)
3025 else:
3026 expected_text = expected_guard
3027 errors.append(output_api.PresubmitPromptWarning(
3028 'Header using the wrong include guard name %s' % guard_name,
3029 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Daniel Bratell00e1b9bc2018-03-12 13:11:123030 'Expected: %r\nFound: %r' % (expected_text, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:143031 else:
3032 # The line after #ifndef should have a #define of the same name.
3033 if line_number == guard_line_number + 1:
3034 expected_line = '#define %s' % guard_name
3035 if line != expected_line:
3036 errors.append(output_api.PresubmitPromptWarning(
3037 'Missing "%s" for include guard' % expected_line,
3038 ['%s:%d' % (f.LocalPath(), line_number + 1)],
3039 'Expected: %r\nGot: %r' % (expected_line, line)))
3040
3041 if not seen_guard_end and line == '#endif // %s' % guard_name:
3042 seen_guard_end = True
3043 elif seen_guard_end:
3044 if line.strip() != '':
3045 errors.append(output_api.PresubmitPromptWarning(
3046 'Include guard %s not covering the whole file' % (
3047 guard_name), [f.LocalPath()]))
3048 break # Nothing else to check and enough to warn once.
3049
3050 if guard_name is None:
3051 errors.append(output_api.PresubmitPromptWarning(
3052 'Missing include guard %s' % expected_guard,
3053 [f.LocalPath()],
3054 'Missing include guard in %s\n'
3055 'Recommended name: %s\n'
3056 'This check can be disabled by having the string\n'
3057 'no-include-guard-because-multiply-included in the header.' %
3058 (f.LocalPath(), expected_guard)))
3059
3060 return errors
3061
3062
mostynbb639aca52015-01-07 20:31:233063def _CheckForWindowsLineEndings(input_api, output_api):
3064 """Check source code and known ascii text files for Windows style line
3065 endings.
3066 """
earthdok1b5e0ee2015-03-10 15:19:103067 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:233068
3069 file_inclusion_pattern = (
3070 known_text_files,
3071 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3072 )
3073
mostynbb639aca52015-01-07 20:31:233074 problems = []
Andrew Grieve933d12e2017-10-30 20:22:533075 source_file_filter = lambda f: input_api.FilterSourceFile(
3076 f, white_list=file_inclusion_pattern, black_list=None)
3077 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:503078 include_file = False
3079 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:233080 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:503081 include_file = True
3082 if include_file:
3083 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:233084
3085 if problems:
3086 return [output_api.PresubmitPromptWarning('Are you sure that you want '
3087 'these files to contain Windows style line endings?\n' +
3088 '\n'.join(problems))]
3089
3090 return []
3091
3092
Vaclav Brozekd5de76a2018-03-17 07:57:503093def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:133094 """Checks that all source files use SYSLOG properly."""
3095 syslog_files = []
3096 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:563097 for line_number, line in f.ChangedContents():
3098 if 'SYSLOG' in line:
3099 syslog_files.append(f.LocalPath() + ':' + str(line_number))
3100
pastarmovj89f7ee12016-09-20 14:58:133101 if syslog_files:
3102 return [output_api.PresubmitPromptWarning(
3103 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
3104 ' calls.\nFiles to check:\n', items=syslog_files)]
3105 return []
3106
3107
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193108def _CheckCrbugLinksHaveHttps(input_api, output_api):
Miguel Casas68bdb652017-12-19 16:29:093109 """Checks that crbug(.com) links are correctly prefixed by https://,
3110 unless they come in the accepted form TODO(crbug.com/...)
3111 """
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193112 white_list = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3113 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS)
3114 sources = lambda f: input_api.FilterSourceFile(
3115 f, white_list=white_list, black_list=black_list)
3116
3117 pattern = input_api.re.compile(r'//.*(?<!:\/\/)crbug[.com]*')
Miguel Casas68bdb652017-12-19 16:29:093118 accepted_pattern = input_api.re.compile(r'//.*TODO\(crbug[.com]*');
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193119 problems = []
3120 for f in input_api.AffectedSourceFiles(sources):
3121 for line_num, line in f.ChangedContents():
Miguel Casas68bdb652017-12-19 16:29:093122 if pattern.search(line) and not accepted_pattern.search(line):
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193123 problems.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
3124
3125 if problems:
3126 return [output_api.PresubmitPromptWarning(
3127 'Found unprefixed crbug.com URL(s), consider prepending https://\n'+
3128 '\n'.join(problems))]
3129 return []
3130
3131
[email protected]1f7b4172010-01-28 01:17:343132def CheckChangeOnUpload(input_api, output_api):
3133 results = []
3134 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:473135 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:283136 results.extend(
jam93a6ee792017-02-08 23:59:223137 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:193138 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:223139 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:133140 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:163141 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193142 results.extend(_CheckCrbugLinksHaveHttps(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543143 return results
[email protected]ca8d1982009-02-19 16:33:123144
3145
[email protected]1bfb8322014-04-23 01:02:413146def GetTryServerMasterForBot(bot):
3147 """Returns the Try Server master for the given bot.
3148
[email protected]0bb112362014-07-26 04:38:323149 It tries to guess the master from the bot name, but may still fail
3150 and return None. There is no longer a default master.
3151 """
3152 # Potentially ambiguous bot names are listed explicitly.
3153 master_map = {
tandriie5587792016-07-14 00:34:503154 'chromium_presubmit': 'master.tryserver.chromium.linux',
3155 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:413156 }
[email protected]0bb112362014-07-26 04:38:323157 master = master_map.get(bot)
3158 if not master:
wnwen4fbaab82016-05-25 12:54:363159 if 'android' in bot:
tandriie5587792016-07-14 00:34:503160 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:363161 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:503162 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:323163 elif 'win' in bot:
tandriie5587792016-07-14 00:34:503164 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:323165 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:503166 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:323167 return master
[email protected]1bfb8322014-04-23 01:02:413168
3169
[email protected]ca8d1982009-02-19 16:33:123170def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:543171 results = []
[email protected]1f7b4172010-01-28 01:17:343172 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543173 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:273174 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:343175 input_api,
3176 output_api,
[email protected]2fdd1f362013-01-16 03:56:033177 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:273178
jam93a6ee792017-02-08 23:59:223179 results.extend(
3180 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:543181 results.extend(input_api.canned_checks.CheckChangeHasBugField(
3182 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:413183 results.extend(input_api.canned_checks.CheckChangeHasDescription(
3184 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543185 return results