blob: 50253ebb70d65fa10ad850b345abf40847af7ea3 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d19842009-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]ca8d19842009-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]ca8d19842009-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]ca8d19842009-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 ),
Matt Menke7f520a82018-03-28 21:38:37546 (
547 'net::URLFetcher',
548 (
549 'net::URLFetcher should no longer be used in content embedders. ',
550 'Instead, use network::SimpleURLLoader instead, which supports ',
551 'an out-of-process network stack. ',
552 'net::URLFetcher may still be used in binaries that do not embed',
553 'content.',
554 ),
Matt Menke59716d02018-04-05 12:45:53555 False,
Matt Menke7f520a82018-03-28 21:38:37556 (
557 r'^ios[\\\/].*\.(cc|h)$',
558 r'.*[\\\/]ios[\\\/].*\.(cc|h)$',
559 r'.*_ios\.(cc|h)$',
560 r'^net[\\\/].*\.(cc|h)$',
561 r'.*[\\\/]tools[\\\/].*\.(cc|h)$',
562 ),
563 ),
[email protected]127f18ec2012-06-16 05:05:59564)
565
wnwenbdc444e2016-05-25 13:44:15566
mlamouria82272622014-09-16 18:45:04567_IPC_ENUM_TRAITS_DEPRECATED = (
568 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50569 'See http://www.chromium.org/Home/chromium-security/education/'
570 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:04571
Shenghua Zhangbfaa38b82017-11-16 21:58:02572_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
573 r".*[\\\/]BuildHooksAndroidImpl\.java",
574 r".*[\\\/]LicenseContentProvider\.java",
575]
[email protected]127f18ec2012-06-16 05:05:59576
Sean Kau46e29bc2017-08-28 16:31:16577# These paths contain test data and other known invalid JSON files.
578_KNOWN_INVALID_JSON_FILE_PATTERNS = [
579 r'test[\\\/]data[\\\/]',
580 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
581 r'^third_party[\\\/]protobuf[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16582 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Sean Kau46e29bc2017-08-28 16:31:16583]
584
585
[email protected]b00342e7f2013-03-26 16:21:54586_VALID_OS_MACROS = (
587 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08588 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54589 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:12590 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:54591 'OS_BSD',
592 'OS_CAT', # For testing.
593 'OS_CHROMEOS',
594 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37595 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54596 'OS_IOS',
597 'OS_LINUX',
598 'OS_MACOSX',
599 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21600 'OS_NACL_NONSFI',
601 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12602 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54603 'OS_OPENBSD',
604 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37605 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54606 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54607 'OS_WIN',
608)
609
610
agrievef32bcc72016-04-04 14:57:40611_ANDROID_SPECIFIC_PYDEPS_FILES = [
612 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04613 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58614 'build/secondary/third_party/android_platform/'
615 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19616 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40617]
618
wnwenbdc444e2016-05-25 13:44:15619
agrievef32bcc72016-04-04 14:57:40620_GENERIC_PYDEPS_FILES = [
John Chencde89192018-01-27 21:18:40621 'chrome/test/chromedriver/test/run_py_tests.pydeps',
agrievef32bcc72016-04-04 14:57:40622]
623
wnwenbdc444e2016-05-25 13:44:15624
agrievef32bcc72016-04-04 14:57:40625_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
626
627
Eric Boren6fd2b932018-01-25 15:05:08628# Bypass the AUTHORS check for these accounts.
629_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:29630 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
631 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
632 'fuchsia-sdk', 'nacl', 'pdfium', 'skia', 'src-internal', 'webrtc')
633 ) | set('%[email protected]' % s for s in ('findit-for-me',))
Eric Boren6fd2b932018-01-25 15:05:08634
635
[email protected]55459852011-08-10 15:17:19636def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
637 """Attempts to prevent use of functions intended only for testing in
638 non-testing code. For now this is just a best-effort implementation
639 that ignores header files and may have some false positives. A
640 better implementation would probably need a proper C++ parser.
641 """
642 # We only scan .cc files and the like, as the declaration of
643 # for-testing functions in header files are hard to distinguish from
644 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44645 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19646
jochenc0d4808c2015-07-27 09:25:42647 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19648 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09649 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19650 exclusion_pattern = input_api.re.compile(
651 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
652 base_function_pattern, base_function_pattern))
653
654 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44655 black_list = (_EXCLUDED_PATHS +
656 _TEST_CODE_EXCLUDED_PATHS +
657 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19658 return input_api.FilterSourceFile(
659 affected_file,
660 white_list=(file_inclusion_pattern, ),
661 black_list=black_list)
662
663 problems = []
664 for f in input_api.AffectedSourceFiles(FilterFile):
665 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24666 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03667 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46668 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03669 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19670 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03671 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19672
673 if problems:
[email protected]f7051d52013-04-02 18:31:42674 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03675 else:
676 return []
[email protected]55459852011-08-10 15:17:19677
678
Vaclav Brozek7dbc28c2018-03-27 08:35:23679def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
680 """This is a simplified version of
681 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
682 """
683 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
684 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
685 name_pattern = r'ForTest(s|ing)?'
686 # Describes an occurrence of "ForTest*" inside a // comment.
687 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
688 # Catch calls.
689 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
690 # Ignore definitions. (Comments are ignored separately.)
691 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
692
693 problems = []
694 sources = lambda x: input_api.FilterSourceFile(
695 x,
696 black_list=(('(?i).*test', r'.*\/junit\/')
697 + input_api.DEFAULT_BLACK_LIST),
698 white_list=(r'.*\.java$',)
699 )
700 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
701 local_path = f.LocalPath()
702 is_inside_javadoc = False
703 for line_number, line in f.ChangedContents():
704 if is_inside_javadoc and javadoc_end_re.search(line):
705 is_inside_javadoc = False
706 if not is_inside_javadoc and javadoc_start_re.search(line):
707 is_inside_javadoc = True
708 if is_inside_javadoc:
709 continue
710 if (inclusion_re.search(line) and
711 not comment_re.search(line) and
712 not exclusion_re.search(line)):
713 problems.append(
714 '%s:%d\n %s' % (local_path, line_number, line.strip()))
715
716 if problems:
717 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
718 else:
719 return []
720
721
[email protected]10689ca2011-09-02 02:31:54722def _CheckNoIOStreamInHeaders(input_api, output_api):
723 """Checks to make sure no .h files include <iostream>."""
724 files = []
725 pattern = input_api.re.compile(r'^#include\s*<iostream>',
726 input_api.re.MULTILINE)
727 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
728 if not f.LocalPath().endswith('.h'):
729 continue
730 contents = input_api.ReadFile(f)
731 if pattern.search(contents):
732 files.append(f)
733
734 if len(files):
yolandyandaabc6d2016-04-18 18:29:39735 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06736 'Do not #include <iostream> in header files, since it inserts static '
737 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54738 '#include <ostream>. See http://crbug.com/94794',
739 files) ]
740 return []
741
742
[email protected]72df4e782012-06-21 16:28:18743def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52744 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18745 problems = []
746 for f in input_api.AffectedFiles():
747 if (not f.LocalPath().endswith(('.cc', '.mm'))):
748 continue
749
750 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04751 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18752 problems.append(' %s:%d' % (f.LocalPath(), line_num))
753
754 if not problems:
755 return []
756 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
757 '\n'.join(problems))]
758
759
danakj61c1aa22015-10-26 19:55:52760def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57761 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52762 errors = []
763 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
764 input_api.re.MULTILINE)
765 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
766 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
767 continue
768 for lnum, line in f.ChangedContents():
769 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17770 errors.append(output_api.PresubmitError(
771 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57772 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17773 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52774 return errors
775
776
mcasasb7440c282015-02-04 14:52:19777def _FindHistogramNameInLine(histogram_name, line):
778 """Tries to find a histogram name or prefix in a line."""
779 if not "affected-histogram" in line:
780 return histogram_name in line
781 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
782 # the histogram_name.
783 if not '"' in line:
784 return False
785 histogram_prefix = line.split('\"')[1]
786 return histogram_prefix in histogram_name
787
788
789def _CheckUmaHistogramChanges(input_api, output_api):
790 """Check that UMA histogram names in touched lines can still be found in other
791 lines of the patch or in histograms.xml. Note that this check would not catch
792 the reverse: changes in histograms.xml not matched in the code itself."""
793 touched_histograms = []
794 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:47795 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
796 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
797 name_pattern = r'"(.*?)"'
798 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
799 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
800 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
801 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
802 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:17803 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:19804 for f in input_api.AffectedFiles():
805 # If histograms.xml itself is modified, keep the modified lines for later.
806 if f.LocalPath().endswith(('histograms.xml')):
807 histograms_xml_modifications = f.ChangedContents()
808 continue
Vaclav Brozekbdac817c2018-03-24 06:30:47809 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
810 single_line_re = single_line_c_re
811 split_line_prefix_re = split_line_c_prefix_re
812 elif f.LocalPath().endswith(('java')):
813 single_line_re = single_line_java_re
814 split_line_prefix_re = split_line_java_prefix_re
815 else:
mcasasb7440c282015-02-04 14:52:19816 continue
817 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:17818 if last_line_matched_prefix:
819 suffix_found = split_line_suffix_re.search(line)
820 if suffix_found :
821 touched_histograms.append([suffix_found.group(1), f, line_num])
822 last_line_matched_prefix = False
823 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:06824 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:19825 if found:
826 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:17827 continue
828 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:19829
830 # Search for the touched histogram names in the local modifications to
831 # histograms.xml, and, if not found, on the base histograms.xml file.
832 unmatched_histograms = []
833 for histogram_info in touched_histograms:
834 histogram_name_found = False
835 for line_num, line in histograms_xml_modifications:
836 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
837 if histogram_name_found:
838 break
839 if not histogram_name_found:
840 unmatched_histograms.append(histogram_info)
841
eromanb90c82e7e32015-04-01 15:13:49842 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19843 problems = []
844 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49845 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19846 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45847 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19848 histogram_name_found = False
849 for line in histograms_xml:
850 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
851 if histogram_name_found:
852 break
853 if not histogram_name_found:
854 problems.append(' [%s:%d] %s' %
855 (f.LocalPath(), line_num, histogram_name))
856
857 if not problems:
858 return []
859 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
860 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49861 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19862
wnwenbdc444e2016-05-25 13:44:15863
yolandyandaabc6d2016-04-18 18:29:39864def _CheckFlakyTestUsage(input_api, output_api):
865 """Check that FlakyTest annotation is our own instead of the android one"""
866 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
867 files = []
868 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
869 if f.LocalPath().endswith('Test.java'):
870 if pattern.search(input_api.ReadFile(f)):
871 files.append(f)
872 if len(files):
873 return [output_api.PresubmitError(
874 'Use org.chromium.base.test.util.FlakyTest instead of '
875 'android.test.FlakyTest',
876 files)]
877 return []
mcasasb7440c282015-02-04 14:52:19878
wnwenbdc444e2016-05-25 13:44:15879
[email protected]8ea5d4b2011-09-13 21:49:22880def _CheckNoNewWStrings(input_api, output_api):
881 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27882 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22883 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20884 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57885 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34886 '/win/' in f.LocalPath() or
887 'chrome_elf' in f.LocalPath() or
888 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20889 continue
[email protected]8ea5d4b2011-09-13 21:49:22890
[email protected]a11dbe9b2012-08-07 01:32:58891 allowWString = False
[email protected]b5c24292011-11-28 14:38:20892 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58893 if 'presubmit: allow wstring' in line:
894 allowWString = True
895 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27896 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58897 allowWString = False
898 else:
899 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22900
[email protected]55463aa62011-10-12 00:48:27901 if not problems:
902 return []
903 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58904 ' If you are calling a cross-platform API that accepts a wstring, '
905 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27906 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22907
908
[email protected]2a8ac9c2011-10-19 17:20:44909def _CheckNoDEPSGIT(input_api, output_api):
910 """Make sure .DEPS.git is never modified manually."""
911 if any(f.LocalPath().endswith('.DEPS.git') for f in
912 input_api.AffectedFiles()):
913 return [output_api.PresubmitError(
914 'Never commit changes to .DEPS.git. This file is maintained by an\n'
915 'automated system based on what\'s in DEPS and your changes will be\n'
916 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50917 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
918 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:44919 'for more information')]
920 return []
921
922
tandriief664692014-09-23 14:51:47923def _CheckValidHostsInDEPS(input_api, output_api):
924 """Checks that DEPS file deps are from allowed_hosts."""
925 # Run only if DEPS file has been modified to annoy fewer bystanders.
926 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
927 return []
928 # Outsource work to gclient verify
929 try:
930 input_api.subprocess.check_output(['gclient', 'verify'])
931 return []
932 except input_api.subprocess.CalledProcessError, error:
933 return [output_api.PresubmitError(
934 'DEPS file must have only git dependencies.',
935 long_text=error.output)]
936
937
[email protected]127f18ec2012-06-16 05:05:59938def _CheckNoBannedFunctions(input_api, output_api):
939 """Make sure that banned functions are not used."""
940 warnings = []
941 errors = []
942
wnwenbdc444e2016-05-25 13:44:15943 def IsBlacklisted(affected_file, blacklist):
944 local_path = affected_file.LocalPath()
945 for item in blacklist:
946 if input_api.re.match(item, local_path):
947 return True
948 return False
949
Sylvain Defresnea8b73d252018-02-28 15:45:54950 def IsIosObcjFile(affected_file):
951 local_path = affected_file.LocalPath()
952 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
953 return False
954 basename = input_api.os_path.basename(local_path)
955 if 'ios' in basename.split('_'):
956 return True
957 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
958 if sep and 'ios' in local_path.split(sep):
959 return True
960 return False
961
wnwenbdc444e2016-05-25 13:44:15962 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
963 matched = False
964 if func_name[0:1] == '/':
965 regex = func_name[1:]
966 if input_api.re.search(regex, line):
967 matched = True
968 elif func_name in line:
dchenge07de812016-06-20 19:27:17969 matched = True
wnwenbdc444e2016-05-25 13:44:15970 if matched:
dchenge07de812016-06-20 19:27:17971 problems = warnings
wnwenbdc444e2016-05-25 13:44:15972 if error:
dchenge07de812016-06-20 19:27:17973 problems = errors
wnwenbdc444e2016-05-25 13:44:15974 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
975 for message_line in message:
976 problems.append(' %s' % message_line)
977
Eric Stevensona9a980972017-09-23 00:04:41978 file_filter = lambda f: f.LocalPath().endswith(('.java'))
979 for f in input_api.AffectedFiles(file_filter=file_filter):
980 for line_num, line in f.ChangedContents():
981 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
982 CheckForMatch(f, line_num, line, func_name, message, error)
983
[email protected]127f18ec2012-06-16 05:05:59984 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
985 for f in input_api.AffectedFiles(file_filter=file_filter):
986 for line_num, line in f.ChangedContents():
987 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15988 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59989
Sylvain Defresnea8b73d252018-02-28 15:45:54990 for f in input_api.AffectedFiles(file_filter=IsIosObcjFile):
991 for line_num, line in f.ChangedContents():
992 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
993 CheckForMatch(f, line_num, line, func_name, message, error)
994
[email protected]127f18ec2012-06-16 05:05:59995 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
996 for f in input_api.AffectedFiles(file_filter=file_filter):
997 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49998 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49999 if IsBlacklisted(f, excluded_paths):
1000 continue
wnwenbdc444e2016-05-25 13:44:151001 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591002
1003 result = []
1004 if (warnings):
1005 result.append(output_api.PresubmitPromptWarning(
1006 'Banned functions were used.\n' + '\n'.join(warnings)))
1007 if (errors):
1008 result.append(output_api.PresubmitError(
1009 'Banned functions were used.\n' + '\n'.join(errors)))
1010 return result
1011
1012
[email protected]6c063c62012-07-11 19:11:061013def _CheckNoPragmaOnce(input_api, output_api):
1014 """Make sure that banned functions are not used."""
1015 files = []
1016 pattern = input_api.re.compile(r'^#pragma\s+once',
1017 input_api.re.MULTILINE)
1018 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1019 if not f.LocalPath().endswith('.h'):
1020 continue
1021 contents = input_api.ReadFile(f)
1022 if pattern.search(contents):
1023 files.append(f)
1024
1025 if files:
1026 return [output_api.PresubmitError(
1027 'Do not use #pragma once in header files.\n'
1028 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1029 files)]
1030 return []
1031
[email protected]127f18ec2012-06-16 05:05:591032
[email protected]e7479052012-09-19 00:26:121033def _CheckNoTrinaryTrueFalse(input_api, output_api):
1034 """Checks to make sure we don't introduce use of foo ? true : false."""
1035 problems = []
1036 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1037 for f in input_api.AffectedFiles():
1038 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1039 continue
1040
1041 for line_num, line in f.ChangedContents():
1042 if pattern.match(line):
1043 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1044
1045 if not problems:
1046 return []
1047 return [output_api.PresubmitPromptWarning(
1048 'Please consider avoiding the "? true : false" pattern if possible.\n' +
1049 '\n'.join(problems))]
1050
1051
[email protected]55f9f382012-07-31 11:02:181052def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:281053 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:181054 change. Breaking - rules is an error, breaking ! rules is a
1055 warning.
1056 """
mohan.reddyf21db962014-10-16 12:26:471057 import sys
[email protected]55f9f382012-07-31 11:02:181058 # We need to wait until we have an input_api object and use this
1059 # roundabout construct to import checkdeps because this file is
1060 # eval-ed and thus doesn't have __file__.
1061 original_sys_path = sys.path
1062 try:
1063 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:471064 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:181065 import checkdeps
1066 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:241067 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:281068 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:181069 from rules import Rule
1070 finally:
1071 # Restore sys.path to what it was before.
1072 sys.path = original_sys_path
1073
1074 added_includes = []
rhalavati08acd232017-04-03 07:23:281075 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:241076 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:181077 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:281078 if CppChecker.IsCppFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501079 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081080 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:281081 elif ProtoChecker.IsProtoFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501082 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081083 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:241084 elif JavaChecker.IsJavaFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501085 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081086 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:181087
[email protected]26385172013-05-09 23:11:351088 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181089
1090 error_descriptions = []
1091 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:281092 error_subjects = set()
1093 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:181094 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
1095 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:081096 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181097 description_with_path = '%s\n %s' % (path, rule_description)
1098 if rule_type == Rule.DISALLOW:
1099 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281100 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:181101 else:
1102 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281103 warning_subjects.add("#includes")
1104
1105 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
1106 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:081107 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:281108 description_with_path = '%s\n %s' % (path, rule_description)
1109 if rule_type == Rule.DISALLOW:
1110 error_descriptions.append(description_with_path)
1111 error_subjects.add("imports")
1112 else:
1113 warning_descriptions.append(description_with_path)
1114 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:181115
Jinsuk Kim5a092672017-10-24 22:42:241116 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:021117 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:081118 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:241119 description_with_path = '%s\n %s' % (path, rule_description)
1120 if rule_type == Rule.DISALLOW:
1121 error_descriptions.append(description_with_path)
1122 error_subjects.add("imports")
1123 else:
1124 warning_descriptions.append(description_with_path)
1125 warning_subjects.add("imports")
1126
[email protected]55f9f382012-07-31 11:02:181127 results = []
1128 if error_descriptions:
1129 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:281130 'You added one or more %s that violate checkdeps rules.'
1131 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:181132 error_descriptions))
1133 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:421134 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:281135 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:181136 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:281137 '%s? See relevant DEPS file(s) for details and contacts.' %
1138 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:181139 warning_descriptions))
1140 return results
1141
1142
[email protected]fbcafe5a2012-08-08 15:31:221143def _CheckFilePermissions(input_api, output_api):
1144 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:151145 if input_api.platform == 'win32':
1146 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:291147 checkperms_tool = input_api.os_path.join(
1148 input_api.PresubmitLocalPath(),
1149 'tools', 'checkperms', 'checkperms.py')
1150 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:471151 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:391152 with input_api.CreateTemporaryFile() as file_list:
1153 for f in input_api.AffectedFiles():
1154 # checkperms.py file/directory arguments must be relative to the
1155 # repository.
1156 file_list.write(f.LocalPath() + '\n')
1157 file_list.close()
1158 args += ['--file-list', file_list.name]
1159 try:
1160 input_api.subprocess.check_output(args)
1161 return []
1162 except input_api.subprocess.CalledProcessError as error:
1163 return [output_api.PresubmitError(
1164 'checkperms.py failed:',
1165 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:221166
1167
robertocn832f5992017-01-04 19:01:301168def _CheckTeamTags(input_api, output_api):
1169 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
1170 checkteamtags_tool = input_api.os_path.join(
1171 input_api.PresubmitLocalPath(),
1172 'tools', 'checkteamtags', 'checkteamtags.py')
1173 args = [input_api.python_executable, checkteamtags_tool,
1174 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:221175 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:301176 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
1177 'OWNERS']
1178 try:
1179 if files:
1180 input_api.subprocess.check_output(args + files)
1181 return []
1182 except input_api.subprocess.CalledProcessError as error:
1183 return [output_api.PresubmitError(
1184 'checkteamtags.py failed:',
1185 long_text=error.output)]
1186
1187
[email protected]c8278b32012-10-30 20:35:491188def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
1189 """Makes sure we don't include ui/aura/window_property.h
1190 in header files.
1191 """
1192 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1193 errors = []
1194 for f in input_api.AffectedFiles():
1195 if not f.LocalPath().endswith('.h'):
1196 continue
1197 for line_num, line in f.ChangedContents():
1198 if pattern.match(line):
1199 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1200
1201 results = []
1202 if errors:
1203 results.append(output_api.PresubmitError(
1204 'Header files should not include ui/aura/window_property.h', errors))
1205 return results
1206
1207
[email protected]70ca77752012-11-20 03:45:031208def _CheckForVersionControlConflictsInFile(input_api, f):
1209 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1210 errors = []
1211 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231212 if f.LocalPath().endswith('.md'):
1213 # First-level headers in markdown look a lot like version control
1214 # conflict markers. http://daringfireball.net/projects/markdown/basics
1215 continue
[email protected]70ca77752012-11-20 03:45:031216 if pattern.match(line):
1217 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1218 return errors
1219
1220
1221def _CheckForVersionControlConflicts(input_api, output_api):
1222 """Usually this is not intentional and will cause a compile failure."""
1223 errors = []
1224 for f in input_api.AffectedFiles():
1225 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1226
1227 results = []
1228 if errors:
1229 results.append(output_api.PresubmitError(
1230 'Version control conflict markers found, please resolve.', errors))
1231 return results
1232
estadee17314a02017-01-12 16:22:161233def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1234 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1235 errors = []
1236 for f in input_api.AffectedFiles():
1237 for line_num, line in f.ChangedContents():
1238 if pattern.search(line):
1239 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1240
1241 results = []
1242 if errors:
1243 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:501244 'Found Google support URL addressed by answer number. Please replace '
1245 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:161246 return results
1247
[email protected]70ca77752012-11-20 03:45:031248
[email protected]06e6d0ff2012-12-11 01:36:441249def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1250 def FilterFile(affected_file):
1251 """Filter function for use with input_api.AffectedSourceFiles,
1252 below. This filters out everything except non-test files from
1253 top-level directories that generally speaking should not hard-code
1254 service URLs (e.g. src/android_webview/, src/content/ and others).
1255 """
1256 return input_api.FilterSourceFile(
1257 affected_file,
[email protected]78bb39d62012-12-11 15:11:561258 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441259 black_list=(_EXCLUDED_PATHS +
1260 _TEST_CODE_EXCLUDED_PATHS +
1261 input_api.DEFAULT_BLACK_LIST))
1262
reillyi38965732015-11-16 18:27:331263 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1264 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461265 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1266 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441267 problems = [] # items are (filename, line_number, line)
1268 for f in input_api.AffectedSourceFiles(FilterFile):
1269 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461270 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441271 problems.append((f.LocalPath(), line_num, line))
1272
1273 if problems:
[email protected]f7051d52013-04-02 18:31:421274 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441275 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581276 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441277 [' %s:%d: %s' % (
1278 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031279 else:
1280 return []
[email protected]06e6d0ff2012-12-11 01:36:441281
1282
[email protected]d2530012013-01-25 16:39:271283def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1284 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311285 The native_client_sdk directory is excluded because it has auto-generated PNG
1286 files for documentation.
[email protected]d2530012013-01-25 16:39:271287 """
[email protected]d2530012013-01-25 16:39:271288 errors = []
binji0dcdf342014-12-12 18:32:311289 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1290 black_list = (r'^native_client_sdk[\\\/]',)
1291 file_filter = lambda f: input_api.FilterSourceFile(
1292 f, white_list=white_list, black_list=black_list)
1293 for f in input_api.AffectedFiles(include_deletes=False,
1294 file_filter=file_filter):
1295 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271296
1297 results = []
1298 if errors:
1299 results.append(output_api.PresubmitError(
1300 'The name of PNG files should not have abbreviations. \n'
1301 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1302 'Contact [email protected] if you have questions.', errors))
1303 return results
1304
1305
Daniel Cheng4dcdb6b2017-04-13 08:30:171306def _ExtractAddRulesFromParsedDeps(parsed_deps):
1307 """Extract the rules that add dependencies from a parsed DEPS file.
1308
1309 Args:
1310 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1311 add_rules = set()
1312 add_rules.update([
1313 rule[1:] for rule in parsed_deps.get('include_rules', [])
1314 if rule.startswith('+') or rule.startswith('!')
1315 ])
Vaclav Brozekd5de76a2018-03-17 07:57:501316 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:171317 {}).iteritems():
1318 add_rules.update([
1319 rule[1:] for rule in rules
1320 if rule.startswith('+') or rule.startswith('!')
1321 ])
1322 return add_rules
1323
1324
1325def _ParseDeps(contents):
1326 """Simple helper for parsing DEPS files."""
1327 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171328 class _VarImpl:
1329
1330 def __init__(self, local_scope):
1331 self._local_scope = local_scope
1332
1333 def Lookup(self, var_name):
1334 """Implements the Var syntax."""
1335 try:
1336 return self._local_scope['vars'][var_name]
1337 except KeyError:
1338 raise Exception('Var is not defined: %s' % var_name)
1339
1340 local_scope = {}
1341 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171342 'Var': _VarImpl(local_scope).Lookup,
1343 }
1344 exec contents in global_scope, local_scope
1345 return local_scope
1346
1347
1348def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081349 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411350 a set of DEPS entries that we should look up.
1351
1352 For a directory (rather than a specific filename) we fake a path to
1353 a specific filename by adding /DEPS. This is chosen as a file that
1354 will seldom or never be subject to per-file include_rules.
1355 """
[email protected]2b438d62013-11-14 17:54:141356 # We ignore deps entries on auto-generated directories.
1357 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081358
Daniel Cheng4dcdb6b2017-04-13 08:30:171359 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1360 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1361
1362 added_deps = new_deps.difference(old_deps)
1363
[email protected]2b438d62013-11-14 17:54:141364 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171365 for added_dep in added_deps:
1366 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1367 continue
1368 # Assume that a rule that ends in .h is a rule for a specific file.
1369 if added_dep.endswith('.h'):
1370 results.add(added_dep)
1371 else:
1372 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081373 return results
1374
1375
[email protected]e871964c2013-05-13 14:14:551376def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1377 """When a dependency prefixed with + is added to a DEPS file, we
1378 want to make sure that the change is reviewed by an OWNER of the
1379 target file or directory, to avoid layering violations from being
1380 introduced. This check verifies that this happens.
1381 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171382 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241383
1384 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191385 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241386 for f in input_api.AffectedFiles(include_deletes=False,
1387 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551388 filename = input_api.os_path.basename(f.LocalPath())
1389 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171390 virtual_depended_on_files.update(_CalculateAddedDeps(
1391 input_api.os_path,
1392 '\n'.join(f.OldContents()),
1393 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551394
[email protected]e871964c2013-05-13 14:14:551395 if not virtual_depended_on_files:
1396 return []
1397
1398 if input_api.is_committing:
1399 if input_api.tbr:
1400 return [output_api.PresubmitNotifyResult(
1401 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271402 if input_api.dry_run:
1403 return [output_api.PresubmitNotifyResult(
1404 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551405 if not input_api.change.issue:
1406 return [output_api.PresubmitError(
1407 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401408 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551409 output = output_api.PresubmitError
1410 else:
1411 output = output_api.PresubmitNotifyResult
1412
1413 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501414 owner_email, reviewers = (
1415 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1416 input_api,
1417 owners_db.email_regexp,
1418 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551419
1420 owner_email = owner_email or input_api.change.author_email
1421
[email protected]de4f7d22013-05-23 14:27:461422 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511423 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461424 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551425 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1426 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411427
1428 # We strip the /DEPS part that was added by
1429 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1430 # directory.
1431 def StripDeps(path):
1432 start_deps = path.rfind('/DEPS')
1433 if start_deps != -1:
1434 return path[:start_deps]
1435 else:
1436 return path
1437 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551438 for path in missing_files]
1439
1440 if unapproved_dependencies:
1441 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151442 output('You need LGTM from owners of depends-on paths in DEPS that were '
1443 'modified in this CL:\n %s' %
1444 '\n '.join(sorted(unapproved_dependencies)))]
1445 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1446 output_list.append(output(
1447 'Suggested missing target path OWNERS:\n %s' %
1448 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551449 return output_list
1450
1451 return []
1452
1453
[email protected]85218562013-11-22 07:41:401454def _CheckSpamLogging(input_api, output_api):
1455 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1456 black_list = (_EXCLUDED_PATHS +
1457 _TEST_CODE_EXCLUDED_PATHS +
1458 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501459 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191460 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481461 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461462 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121463 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1464 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581465 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161466 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031467 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151468 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1469 r"^chromecast[\\\/]",
1470 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481471 r"^components[\\\/]browser_watcher[\\\/]"
1472 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311473 r"^components[\\\/]html_viewer[\\\/]"
1474 r"web_test_delegate_impl\.cc$",
Samuel Huang577ef6c2018-03-13 18:19:341475 r"^components[\\\/]zucchini[\\\/].*",
peter80739bb2015-10-20 11:17:461476 # TODO(peter): Remove this exception. https://crbug.com/534537
1477 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1478 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251479 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1480 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241481 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111482 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151483 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111484 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521485 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501486 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361487 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311488 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131489 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001490 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441491 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451492 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021493 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351494 r"dump_file_system.cc$",
1495 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401496 source_file_filter = lambda x: input_api.FilterSourceFile(
1497 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1498
thomasanderson625d3932017-03-29 07:16:581499 log_info = set([])
1500 printf = set([])
[email protected]85218562013-11-22 07:41:401501
1502 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581503 for _, line in f.ChangedContents():
1504 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1505 log_info.add(f.LocalPath())
1506 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1507 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371508
thomasanderson625d3932017-03-29 07:16:581509 if input_api.re.search(r"\bprintf\(", line):
1510 printf.add(f.LocalPath())
1511 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1512 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401513
1514 if log_info:
1515 return [output_api.PresubmitError(
1516 'These files spam the console log with LOG(INFO):',
1517 items=log_info)]
1518 if printf:
1519 return [output_api.PresubmitError(
1520 'These files spam the console log with printf/fprintf:',
1521 items=printf)]
1522 return []
1523
1524
[email protected]49aa76a2013-12-04 06:59:161525def _CheckForAnonymousVariables(input_api, output_api):
1526 """These types are all expected to hold locks while in scope and
1527 so should never be anonymous (which causes them to be immediately
1528 destroyed)."""
1529 they_who_must_be_named = [
1530 'base::AutoLock',
1531 'base::AutoReset',
1532 'base::AutoUnlock',
1533 'SkAutoAlphaRestore',
1534 'SkAutoBitmapShaderInstall',
1535 'SkAutoBlitterChoose',
1536 'SkAutoBounderCommit',
1537 'SkAutoCallProc',
1538 'SkAutoCanvasRestore',
1539 'SkAutoCommentBlock',
1540 'SkAutoDescriptor',
1541 'SkAutoDisableDirectionCheck',
1542 'SkAutoDisableOvalCheck',
1543 'SkAutoFree',
1544 'SkAutoGlyphCache',
1545 'SkAutoHDC',
1546 'SkAutoLockColors',
1547 'SkAutoLockPixels',
1548 'SkAutoMalloc',
1549 'SkAutoMaskFreeImage',
1550 'SkAutoMutexAcquire',
1551 'SkAutoPathBoundsUpdate',
1552 'SkAutoPDFRelease',
1553 'SkAutoRasterClipValidate',
1554 'SkAutoRef',
1555 'SkAutoTime',
1556 'SkAutoTrace',
1557 'SkAutoUnref',
1558 ]
1559 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1560 # bad: base::AutoLock(lock.get());
1561 # not bad: base::AutoLock lock(lock.get());
1562 bad_pattern = input_api.re.compile(anonymous)
1563 # good: new base::AutoLock(lock.get())
1564 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1565 errors = []
1566
1567 for f in input_api.AffectedFiles():
1568 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1569 continue
1570 for linenum, line in f.ChangedContents():
1571 if bad_pattern.search(line) and not good_pattern.search(line):
1572 errors.append('%s:%d' % (f.LocalPath(), linenum))
1573
1574 if errors:
1575 return [output_api.PresubmitError(
1576 'These lines create anonymous variables that need to be named:',
1577 items=errors)]
1578 return []
1579
1580
Peter Kasting4844e46e2018-02-23 07:27:101581def _CheckUniquePtr(input_api, output_api):
1582 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1583 sources = lambda affected_file: input_api.FilterSourceFile(
1584 affected_file,
1585 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1586 input_api.DEFAULT_BLACK_LIST),
1587 white_list=(file_inclusion_pattern,))
Vaclav Brozeka54c528b2018-04-06 19:23:551588
1589 # Pattern to capture a single "<...>" block of template arguments. It can
1590 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
1591 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
1592 # latter would likely require counting that < and > match, which is not
1593 # expressible in regular languages. Should the need arise, one can introduce
1594 # limited counting (matching up to a total number of nesting depth), which
1595 # should cover all practical cases for already a low nesting limit.
1596 template_arg_pattern = (
1597 r'<[^>]*' # Opening block of <.
1598 r'>([^<]*>)?') # Closing block of >.
1599 # Prefix expressing that whatever follows is not already inside a <...>
1600 # block.
1601 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:101602 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:551603 not_inside_template_arg_pattern
1604 + r'\bstd::unique_ptr'
1605 + template_arg_pattern
1606 + r'\(\)')
1607
1608 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
1609 template_arg_no_array_pattern = (
1610 r'<[^>]*[^]]' # Opening block of <.
1611 r'>([^(<]*[^]]>)?') # Closing block of >.
1612 # Prefix saying that what follows is the start of an expression.
1613 start_of_expr_pattern = r'(=|\breturn|^)\s*'
1614 # Suffix saying that what follows are call parentheses with a non-empty list
1615 # of arguments.
1616 nonempty_arg_list_pattern = r'\(([^)]|$)'
1617 return_construct_pattern = input_api.re.compile(
1618 start_of_expr_pattern
1619 + r'std::unique_ptr'
1620 + template_arg_no_array_pattern
1621 + nonempty_arg_list_pattern)
1622
Vaclav Brozek851d9602018-04-04 16:13:051623 problems_constructor = []
1624 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:101625 for f in input_api.AffectedSourceFiles(sources):
1626 for line_number, line in f.ChangedContents():
1627 # Disallow:
1628 # return std::unique_ptr<T>(foo);
1629 # bar = std::unique_ptr<T>(foo);
1630 # But allow:
1631 # return std::unique_ptr<T[]>(foo);
1632 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozek851d9602018-04-04 16:13:051633 local_path = f.LocalPath()
Peter Kasting4844e46e2018-02-23 07:27:101634 if return_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:051635 problems_constructor.append(
1636 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:101637 # Disallow:
1638 # std::unique_ptr<T>()
1639 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:051640 problems_nullptr.append(
1641 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1642
1643 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:161644 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:051645 errors.append(output_api.PresubmitError(
1646 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:161647 problems_nullptr))
1648 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:051649 errors.append(output_api.PresubmitError(
1650 'The following files use explicit std::unique_ptr constructor.'
1651 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:161652 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:101653 return errors
1654
1655
[email protected]999261d2014-03-03 20:08:081656def _CheckUserActionUpdate(input_api, output_api):
1657 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521658 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081659 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521660 # If actions.xml is already included in the changelist, the PRESUBMIT
1661 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081662 return []
1663
[email protected]999261d2014-03-03 20:08:081664 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1665 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521666 current_actions = None
[email protected]999261d2014-03-03 20:08:081667 for f in input_api.AffectedFiles(file_filter=file_filter):
1668 for line_num, line in f.ChangedContents():
1669 match = input_api.re.search(action_re, line)
1670 if match:
[email protected]2f92dec2014-03-07 19:21:521671 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1672 # loaded only once.
1673 if not current_actions:
1674 with open('tools/metrics/actions/actions.xml') as actions_f:
1675 current_actions = actions_f.read()
1676 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081677 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521678 action = 'name="{0}"'.format(action_name)
1679 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081680 return [output_api.PresubmitPromptWarning(
1681 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521682 'tools/metrics/actions/actions.xml. Please run '
1683 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081684 % (f.LocalPath(), line_num, action_name))]
1685 return []
1686
1687
Daniel Cheng13ca61a882017-08-25 15:11:251688def _ImportJSONCommentEater(input_api):
1689 import sys
1690 sys.path = sys.path + [input_api.os_path.join(
1691 input_api.PresubmitLocalPath(),
1692 'tools', 'json_comment_eater')]
1693 import json_comment_eater
1694 return json_comment_eater
1695
1696
[email protected]99171a92014-06-03 08:44:471697def _GetJSONParseError(input_api, filename, eat_comments=True):
1698 try:
1699 contents = input_api.ReadFile(filename)
1700 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251701 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131702 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471703
1704 input_api.json.loads(contents)
1705 except ValueError as e:
1706 return e
1707 return None
1708
1709
1710def _GetIDLParseError(input_api, filename):
1711 try:
1712 contents = input_api.ReadFile(filename)
1713 idl_schema = input_api.os_path.join(
1714 input_api.PresubmitLocalPath(),
1715 'tools', 'json_schema_compiler', 'idl_schema.py')
1716 process = input_api.subprocess.Popen(
1717 [input_api.python_executable, idl_schema],
1718 stdin=input_api.subprocess.PIPE,
1719 stdout=input_api.subprocess.PIPE,
1720 stderr=input_api.subprocess.PIPE,
1721 universal_newlines=True)
1722 (_, error) = process.communicate(input=contents)
1723 return error or None
1724 except ValueError as e:
1725 return e
1726
1727
1728def _CheckParseErrors(input_api, output_api):
1729 """Check that IDL and JSON files do not contain syntax errors."""
1730 actions = {
1731 '.idl': _GetIDLParseError,
1732 '.json': _GetJSONParseError,
1733 }
[email protected]99171a92014-06-03 08:44:471734 # Most JSON files are preprocessed and support comments, but these do not.
1735 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491736 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471737 ]
1738 # Only run IDL checker on files in these directories.
1739 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491740 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1741 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471742 ]
1743
1744 def get_action(affected_file):
1745 filename = affected_file.LocalPath()
1746 return actions.get(input_api.os_path.splitext(filename)[1])
1747
[email protected]99171a92014-06-03 08:44:471748 def FilterFile(affected_file):
1749 action = get_action(affected_file)
1750 if not action:
1751 return False
1752 path = affected_file.LocalPath()
1753
Sean Kau46e29bc2017-08-28 16:31:161754 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471755 return False
1756
1757 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161758 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471759 return False
1760 return True
1761
1762 results = []
1763 for affected_file in input_api.AffectedFiles(
1764 file_filter=FilterFile, include_deletes=False):
1765 action = get_action(affected_file)
1766 kwargs = {}
1767 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161768 _MatchesFile(input_api, json_no_comments_patterns,
1769 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471770 kwargs['eat_comments'] = False
1771 parse_error = action(input_api,
1772 affected_file.AbsoluteLocalPath(),
1773 **kwargs)
1774 if parse_error:
1775 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1776 (affected_file.LocalPath(), parse_error)))
1777 return results
1778
1779
[email protected]760deea2013-12-10 19:33:491780def _CheckJavaStyle(input_api, output_api):
1781 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471782 import sys
[email protected]760deea2013-12-10 19:33:491783 original_sys_path = sys.path
1784 try:
1785 sys.path = sys.path + [input_api.os_path.join(
1786 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1787 import checkstyle
1788 finally:
1789 # Restore sys.path to what it was before.
1790 sys.path = original_sys_path
1791
1792 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091793 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511794 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491795
1796
Sean Kau46e29bc2017-08-28 16:31:161797def _MatchesFile(input_api, patterns, path):
1798 for pattern in patterns:
1799 if input_api.re.search(pattern, path):
1800 return True
1801 return False
1802
1803
Daniel Cheng7052cdf2017-11-21 19:23:291804def _GetOwnersFilesToCheckForIpcOwners(input_api):
1805 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:171806
Daniel Cheng7052cdf2017-11-21 19:23:291807 Returns:
1808 A dictionary mapping an OWNER file to the list of OWNERS rules it must
1809 contain to cover IPC-related files with noparent reviewer rules.
1810 """
1811 # Whether or not a file affects IPC is (mostly) determined by a simple list
1812 # of filename patterns.
dchenge07de812016-06-20 19:27:171813 file_patterns = [
palmerb19a0932017-01-24 04:00:311814 # Legacy IPC:
dchenge07de812016-06-20 19:27:171815 '*_messages.cc',
1816 '*_messages*.h',
1817 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311818 # Mojo IPC:
dchenge07de812016-06-20 19:27:171819 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:471820 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:171821 '*_struct_traits*.*',
1822 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311823 '*.typemap',
1824 # Android native IPC:
1825 '*.aidl',
1826 # Blink uses a different file naming convention:
1827 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:471828 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:171829 '*StructTraits*.*',
1830 '*TypeConverter*.*',
1831 ]
1832
scottmg7a6ed5ba2016-11-04 18:22:041833 # These third_party directories do not contain IPCs, but contain files
1834 # matching the above patterns, which trigger false positives.
1835 exclude_paths = [
1836 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291837 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041838 ]
1839
dchenge07de812016-06-20 19:27:171840 # Dictionary mapping an OWNERS file path to Patterns.
1841 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1842 # rules ) to a PatternEntry.
1843 # PatternEntry is a dictionary with two keys:
1844 # - 'files': the files that are matched by this pattern
1845 # - 'rules': the per-file rules needed for this pattern
1846 # For example, if we expect OWNERS file to contain rules for *.mojom and
1847 # *_struct_traits*.*, Patterns might look like this:
1848 # {
1849 # '*.mojom': {
1850 # 'files': ...,
1851 # 'rules': [
1852 # 'per-file *.mojom=set noparent',
1853 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1854 # ],
1855 # },
1856 # '*_struct_traits*.*': {
1857 # 'files': ...,
1858 # 'rules': [
1859 # 'per-file *_struct_traits*.*=set noparent',
1860 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1861 # ],
1862 # },
1863 # }
1864 to_check = {}
1865
Daniel Cheng13ca61a882017-08-25 15:11:251866 def AddPatternToCheck(input_file, pattern):
1867 owners_file = input_api.os_path.join(
1868 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1869 if owners_file not in to_check:
1870 to_check[owners_file] = {}
1871 if pattern not in to_check[owners_file]:
1872 to_check[owners_file][pattern] = {
1873 'files': [],
1874 'rules': [
1875 'per-file %s=set noparent' % pattern,
1876 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1877 ]
1878 }
Vaclav Brozekd5de76a2018-03-17 07:57:501879 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:251880
dchenge07de812016-06-20 19:27:171881 # Iterate through the affected files to see what we actually need to check
1882 # for. We should only nag patch authors about per-file rules if a file in that
1883 # directory would match that pattern. If a directory only contains *.mojom
1884 # files and no *_messages*.h files, we should only nag about rules for
1885 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251886 for f in input_api.AffectedFiles(include_deletes=False):
1887 # Manifest files don't have a strong naming convention. Instead, scan
1888 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161889 if (f.LocalPath().endswith('.json') and
1890 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1891 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251892 json_comment_eater = _ImportJSONCommentEater(input_api)
1893 mostly_json_lines = '\n'.join(f.NewContents())
1894 # Comments aren't allowed in strict JSON, so filter them out.
1895 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:431896 try:
1897 json_content = input_api.json.loads(json_lines)
1898 except:
1899 # There's another PRESUBMIT check that already verifies that JSON files
1900 # are not invalid, so no need to emit another warning here.
1901 continue
Daniel Cheng13ca61a882017-08-25 15:11:251902 if 'interface_provider_specs' in json_content:
1903 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171904 for pattern in file_patterns:
1905 if input_api.fnmatch.fnmatch(
1906 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041907 skip = False
1908 for exclude in exclude_paths:
1909 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1910 skip = True
1911 break
1912 if skip:
1913 continue
Daniel Cheng13ca61a882017-08-25 15:11:251914 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171915 break
1916
Daniel Cheng7052cdf2017-11-21 19:23:291917 return to_check
1918
1919
1920def _CheckIpcOwners(input_api, output_api):
1921 """Checks that affected files involving IPC have an IPC OWNERS rule."""
1922 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
1923
1924 if to_check:
1925 # If there are any OWNERS files to check, there are IPC-related changes in
1926 # this CL. Auto-CC the review list.
1927 output_api.AppendCC('[email protected]')
1928
1929 # Go through the OWNERS files to check, filtering out rules that are already
1930 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:171931 for owners_file, patterns in to_check.iteritems():
1932 try:
1933 with file(owners_file) as f:
1934 lines = set(f.read().splitlines())
1935 for entry in patterns.itervalues():
1936 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1937 ]
1938 except IOError:
1939 # No OWNERS file, so all the rules are definitely missing.
1940 continue
1941
1942 # All the remaining lines weren't found in OWNERS files, so emit an error.
1943 errors = []
1944 for owners_file, patterns in to_check.iteritems():
1945 missing_lines = []
1946 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:501947 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:171948 missing_lines.extend(entry['rules'])
1949 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1950 if missing_lines:
1951 errors.append(
Daniel Cheng52111692017-06-14 08:00:591952 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171953 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1954
1955 results = []
1956 if errors:
vabrf5ce3bf92016-07-11 14:52:411957 if input_api.is_committing:
1958 output = output_api.PresubmitError
1959 else:
1960 output = output_api.PresubmitPromptWarning
1961 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591962 'Found OWNERS files that need to be updated for IPC security ' +
1963 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171964 long_text='\n\n'.join(errors)))
1965
1966 return results
1967
1968
jbriance9e12f162016-11-25 07:57:501969def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311970 """Checks that added or removed lines in non third party affected
1971 header files do not lead to new useless class or struct forward
1972 declaration.
jbriance9e12f162016-11-25 07:57:501973 """
1974 results = []
1975 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1976 input_api.re.MULTILINE)
1977 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1978 input_api.re.MULTILINE)
1979 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311980 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191981 not f.LocalPath().startswith('third_party/blink') and
1982 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311983 not f.LocalPath().startswith('third_party/WebKit') and
1984 not f.LocalPath().startswith('third_party\\WebKit')):
1985 continue
1986
jbriance9e12f162016-11-25 07:57:501987 if not f.LocalPath().endswith('.h'):
1988 continue
1989
1990 contents = input_api.ReadFile(f)
1991 fwd_decls = input_api.re.findall(class_pattern, contents)
1992 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1993
1994 useless_fwd_decls = []
1995 for decl in fwd_decls:
1996 count = sum(1 for _ in input_api.re.finditer(
1997 r'\b%s\b' % input_api.re.escape(decl), contents))
1998 if count == 1:
1999 useless_fwd_decls.append(decl)
2000
2001 if not useless_fwd_decls:
2002 continue
2003
2004 for line in f.GenerateScmDiff().splitlines():
2005 if (line.startswith('-') and not line.startswith('--') or
2006 line.startswith('+') and not line.startswith('++')):
2007 for decl in useless_fwd_decls:
2008 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
2009 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:242010 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:502011 (f.LocalPath(), decl)))
2012 useless_fwd_decls.remove(decl)
2013
2014 return results
2015
2016
dskiba88634f4e2015-08-14 23:03:292017def _CheckAndroidToastUsage(input_api, output_api):
2018 """Checks that code uses org.chromium.ui.widget.Toast instead of
2019 android.widget.Toast (Chromium Toast doesn't force hardware
2020 acceleration on low-end devices, saving memory).
2021 """
2022 toast_import_pattern = input_api.re.compile(
2023 r'^import android\.widget\.Toast;$')
2024
2025 errors = []
2026
2027 sources = lambda affected_file: input_api.FilterSourceFile(
2028 affected_file,
2029 black_list=(_EXCLUDED_PATHS +
2030 _TEST_CODE_EXCLUDED_PATHS +
2031 input_api.DEFAULT_BLACK_LIST +
2032 (r'^chromecast[\\\/].*',
2033 r'^remoting[\\\/].*')),
2034 white_list=(r'.*\.java$',))
2035
2036 for f in input_api.AffectedSourceFiles(sources):
2037 for line_num, line in f.ChangedContents():
2038 if toast_import_pattern.search(line):
2039 errors.append("%s:%d" % (f.LocalPath(), line_num))
2040
2041 results = []
2042
2043 if errors:
2044 results.append(output_api.PresubmitError(
2045 'android.widget.Toast usage is detected. Android toasts use hardware'
2046 ' acceleration, and can be\ncostly on low-end devices. Please use'
2047 ' org.chromium.ui.widget.Toast instead.\n'
2048 'Contact [email protected] if you have any questions.',
2049 errors))
2050
2051 return results
2052
2053
dgnaa68d5e2015-06-10 10:08:222054def _CheckAndroidCrLogUsage(input_api, output_api):
2055 """Checks that new logs using org.chromium.base.Log:
2056 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:512057 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:222058 """
pkotwicza1dd0b002016-05-16 14:41:042059
torne89540622017-03-24 19:41:302060 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:042061 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:302062 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:042063 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:302064 # WebView license viewer code cannot depend on //base; used in stub APK.
2065 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
2066 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:042067 ]
2068
dgnaa68d5e2015-06-10 10:08:222069 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:122070 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
2071 class_in_base_pattern = input_api.re.compile(
2072 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
2073 has_some_log_import_pattern = input_api.re.compile(
2074 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222075 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:122076 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:222077 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:512078 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:222079 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222080
Vincent Scheib16d7b272015-09-15 18:09:072081 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:222082 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:042083 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
2084 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:122085
dgnaa68d5e2015-06-10 10:08:222086 tag_decl_errors = []
2087 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:122088 tag_errors = []
dgn38736db2015-09-18 19:20:512089 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:122090 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:222091
2092 for f in input_api.AffectedSourceFiles(sources):
2093 file_content = input_api.ReadFile(f)
2094 has_modified_logs = False
2095
2096 # Per line checks
dgn87d9fb62015-06-12 09:15:122097 if (cr_log_import_pattern.search(file_content) or
2098 (class_in_base_pattern.search(file_content) and
2099 not has_some_log_import_pattern.search(file_content))):
2100 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:222101 for line_num, line in f.ChangedContents():
2102
2103 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:122104 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:222105 if match:
2106 has_modified_logs = True
2107
2108 # Make sure it uses "TAG"
2109 if not match.group('tag') == 'TAG':
2110 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:122111 else:
2112 # Report non cr Log function calls in changed lines
2113 for line_num, line in f.ChangedContents():
2114 if log_call_pattern.search(line):
2115 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:222116
2117 # Per file checks
2118 if has_modified_logs:
2119 # Make sure the tag is using the "cr" prefix and is not too long
2120 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:512121 tag_name = match.group('name') if match else None
2122 if not tag_name:
dgnaa68d5e2015-06-10 10:08:222123 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512124 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:222125 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512126 elif '.' in tag_name:
2127 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:222128
2129 results = []
2130 if tag_decl_errors:
2131 results.append(output_api.PresubmitPromptWarning(
2132 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:512133 '"private static final String TAG = "<package tag>".\n'
2134 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222135 tag_decl_errors))
2136
2137 if tag_length_errors:
2138 results.append(output_api.PresubmitError(
2139 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:512140 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222141 tag_length_errors))
2142
2143 if tag_errors:
2144 results.append(output_api.PresubmitPromptWarning(
2145 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
2146 tag_errors))
2147
dgn87d9fb62015-06-12 09:15:122148 if util_log_errors:
dgn4401aa52015-04-29 16:26:172149 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:122150 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
2151 util_log_errors))
2152
dgn38736db2015-09-18 19:20:512153 if tag_with_dot_errors:
2154 results.append(output_api.PresubmitPromptWarning(
2155 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
2156 tag_with_dot_errors))
2157
dgn4401aa52015-04-29 16:26:172158 return results
2159
2160
Yoland Yanb92fa522017-08-28 17:37:062161def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
2162 """Checks that junit.framework.* is no longer used."""
2163 deprecated_junit_framework_pattern = input_api.re.compile(
2164 r'^import junit\.framework\..*;',
2165 input_api.re.MULTILINE)
2166 sources = lambda x: input_api.FilterSourceFile(
2167 x, white_list=(r'.*\.java$',), black_list=None)
2168 errors = []
2169 for f in input_api.AffectedFiles(sources):
2170 for line_num, line in f.ChangedContents():
2171 if deprecated_junit_framework_pattern.search(line):
2172 errors.append("%s:%d" % (f.LocalPath(), line_num))
2173
2174 results = []
2175 if errors:
2176 results.append(output_api.PresubmitError(
2177 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
2178 '(org.junit.*) from //third_party/junit. Contact [email protected]'
2179 ' if you have any question.', errors))
2180 return results
2181
2182
2183def _CheckAndroidTestJUnitInheritance(input_api, output_api):
2184 """Checks that if new Java test classes have inheritance.
2185 Either the new test class is JUnit3 test or it is a JUnit4 test class
2186 with a base class, either case is undesirable.
2187 """
2188 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
2189
2190 sources = lambda x: input_api.FilterSourceFile(
2191 x, white_list=(r'.*Test\.java$',), black_list=None)
2192 errors = []
2193 for f in input_api.AffectedFiles(sources):
2194 if not f.OldContents():
2195 class_declaration_start_flag = False
2196 for line_num, line in f.ChangedContents():
2197 if class_declaration_pattern.search(line):
2198 class_declaration_start_flag = True
2199 if class_declaration_start_flag and ' extends ' in line:
2200 errors.append('%s:%d' % (f.LocalPath(), line_num))
2201 if '{' in line:
2202 class_declaration_start_flag = False
2203
2204 results = []
2205 if errors:
2206 results.append(output_api.PresubmitPromptWarning(
2207 'The newly created files include Test classes that inherits from base'
2208 ' class. Please do not use inheritance in JUnit4 tests or add new'
2209 ' JUnit3 tests. Contact [email protected] if you have any'
2210 ' questions.', errors))
2211 return results
2212
yolandyan45001472016-12-21 21:12:422213def _CheckAndroidTestAnnotationUsage(input_api, output_api):
2214 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
2215 deprecated_annotation_import_pattern = input_api.re.compile(
2216 r'^import android\.test\.suitebuilder\.annotation\..*;',
2217 input_api.re.MULTILINE)
2218 sources = lambda x: input_api.FilterSourceFile(
2219 x, white_list=(r'.*\.java$',), black_list=None)
2220 errors = []
2221 for f in input_api.AffectedFiles(sources):
2222 for line_num, line in f.ChangedContents():
2223 if deprecated_annotation_import_pattern.search(line):
2224 errors.append("%s:%d" % (f.LocalPath(), line_num))
2225
2226 results = []
2227 if errors:
2228 results.append(output_api.PresubmitError(
2229 'Annotations in android.test.suitebuilder.annotation have been'
2230 ' deprecated since API level 24. Please use android.support.test.filters'
2231 ' from //third_party/android_support_test_runner:runner_java instead.'
2232 ' Contact [email protected] if you have any questions.', errors))
2233 return results
2234
2235
agrieve7b6479d82015-10-07 14:24:222236def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
2237 """Checks if MDPI assets are placed in a correct directory."""
2238 file_filter = lambda f: (f.LocalPath().endswith('.png') and
2239 ('/res/drawable/' in f.LocalPath() or
2240 '/res/drawable-ldrtl/' in f.LocalPath()))
2241 errors = []
2242 for f in input_api.AffectedFiles(include_deletes=False,
2243 file_filter=file_filter):
2244 errors.append(' %s' % f.LocalPath())
2245
2246 results = []
2247 if errors:
2248 results.append(output_api.PresubmitError(
2249 'MDPI assets should be placed in /res/drawable-mdpi/ or '
2250 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
2251 '/res/drawable-ldrtl/.\n'
2252 'Contact [email protected] if you have questions.', errors))
2253 return results
2254
2255
Nate Fischer535972b2017-09-16 01:06:182256def _CheckAndroidWebkitImports(input_api, output_api):
2257 """Checks that code uses org.chromium.base.Callback instead of
2258 android.widget.ValueCallback except in the WebView glue layer.
2259 """
2260 valuecallback_import_pattern = input_api.re.compile(
2261 r'^import android\.webkit\.ValueCallback;$')
2262
2263 errors = []
2264
2265 sources = lambda affected_file: input_api.FilterSourceFile(
2266 affected_file,
2267 black_list=(_EXCLUDED_PATHS +
2268 _TEST_CODE_EXCLUDED_PATHS +
2269 input_api.DEFAULT_BLACK_LIST +
2270 (r'^android_webview[\\\/]glue[\\\/].*',)),
2271 white_list=(r'.*\.java$',))
2272
2273 for f in input_api.AffectedSourceFiles(sources):
2274 for line_num, line in f.ChangedContents():
2275 if valuecallback_import_pattern.search(line):
2276 errors.append("%s:%d" % (f.LocalPath(), line_num))
2277
2278 results = []
2279
2280 if errors:
2281 results.append(output_api.PresubmitError(
2282 'android.webkit.ValueCallback usage is detected outside of the glue'
2283 ' layer. To stay compatible with the support library, android.webkit.*'
2284 ' classes should only be used inside the glue layer and'
2285 ' org.chromium.base.Callback should be used instead.',
2286 errors))
2287
2288 return results
2289
2290
agrievef32bcc72016-04-04 14:57:402291class PydepsChecker(object):
2292 def __init__(self, input_api, pydeps_files):
2293 self._file_cache = {}
2294 self._input_api = input_api
2295 self._pydeps_files = pydeps_files
2296
2297 def _LoadFile(self, path):
2298 """Returns the list of paths within a .pydeps file relative to //."""
2299 if path not in self._file_cache:
2300 with open(path) as f:
2301 self._file_cache[path] = f.read()
2302 return self._file_cache[path]
2303
2304 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
2305 """Returns an interable of paths within the .pydep, relativized to //."""
2306 os_path = self._input_api.os_path
2307 pydeps_dir = os_path.dirname(pydeps_path)
2308 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2309 if not l.startswith('*'))
2310 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2311
2312 def _CreateFilesToPydepsMap(self):
2313 """Returns a map of local_path -> list_of_pydeps."""
2314 ret = {}
2315 for pydep_local_path in self._pydeps_files:
2316 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2317 ret.setdefault(path, []).append(pydep_local_path)
2318 return ret
2319
2320 def ComputeAffectedPydeps(self):
2321 """Returns an iterable of .pydeps files that might need regenerating."""
2322 affected_pydeps = set()
2323 file_to_pydeps_map = None
2324 for f in self._input_api.AffectedFiles(include_deletes=True):
2325 local_path = f.LocalPath()
2326 if local_path == 'DEPS':
2327 return self._pydeps_files
2328 elif local_path.endswith('.pydeps'):
2329 if local_path in self._pydeps_files:
2330 affected_pydeps.add(local_path)
2331 elif local_path.endswith('.py'):
2332 if file_to_pydeps_map is None:
2333 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2334 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2335 return affected_pydeps
2336
2337 def DetermineIfStale(self, pydeps_path):
2338 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412339 import difflib
John Budorick47ca3fe2018-02-10 00:53:102340 import os
2341
agrievef32bcc72016-04-04 14:57:402342 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2343 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:102344 env = dict(os.environ)
2345 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:402346 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:102347 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412348 old_contents = old_pydeps_data[2:]
2349 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402350 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412351 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402352
2353
2354def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2355 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:402356 # This check is for Python dependency lists (.pydeps files), and involves
2357 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
2358 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:282359 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002360 return []
Mostyn Bramley-Moore6b427322017-12-21 22:11:022361 # TODO(agrieve): Update when there's a better way to detect
2362 # this: crbug.com/570091
agrievef32bcc72016-04-04 14:57:402363 is_android = input_api.os_path.exists('third_party/android_tools')
2364 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2365 results = []
2366 # First, check for new / deleted .pydeps.
2367 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:032368 # Check whether we are running the presubmit check for a file in src.
2369 # f.LocalPath is relative to repo (src, or internal repo).
2370 # os_path.exists is relative to src repo.
2371 # Therefore if os_path.exists is true, it means f.LocalPath is relative
2372 # to src and we can conclude that the pydeps is in src.
2373 if input_api.os_path.exists(f.LocalPath()):
2374 if f.LocalPath().endswith('.pydeps'):
2375 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2376 results.append(output_api.PresubmitError(
2377 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2378 'remove %s' % f.LocalPath()))
2379 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2380 results.append(output_api.PresubmitError(
2381 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2382 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:402383
2384 if results:
2385 return results
2386
2387 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2388
2389 for pydep_path in checker.ComputeAffectedPydeps():
2390 try:
phajdan.jr0d9878552016-11-04 10:49:412391 result = checker.DetermineIfStale(pydep_path)
2392 if result:
2393 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402394 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412395 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2396 'To regenerate, run:\n\n %s' %
2397 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402398 except input_api.subprocess.CalledProcessError as error:
2399 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2400 long_text=error.output)]
2401
2402 return results
2403
2404
glidere61efad2015-02-18 17:39:432405def _CheckSingletonInHeaders(input_api, output_api):
2406 """Checks to make sure no header files have |Singleton<|."""
2407 def FileFilter(affected_file):
2408 # It's ok for base/memory/singleton.h to have |Singleton<|.
2409 black_list = (_EXCLUDED_PATHS +
2410 input_api.DEFAULT_BLACK_LIST +
Michael Warrese4451492018-03-07 04:42:472411 (r"^base[\\\/]memory[\\\/]singleton\.h$",
2412 r"^net[\\\/]quic[\\\/]platform[\\\/]impl[\\\/]"
2413 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:432414 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2415
sergeyu34d21222015-09-16 00:11:442416 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432417 files = []
2418 for f in input_api.AffectedSourceFiles(FileFilter):
2419 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2420 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2421 contents = input_api.ReadFile(f)
2422 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242423 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432424 pattern.search(line)):
2425 files.append(f)
2426 break
2427
2428 if files:
yolandyandaabc6d2016-04-18 18:29:392429 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442430 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432431 'Please move them to an appropriate source file so that the ' +
2432 'template gets instantiated in a single compilation unit.',
2433 files) ]
2434 return []
2435
2436
[email protected]fd20b902014-05-09 02:14:532437_DEPRECATED_CSS = [
2438 # Values
2439 ( "-webkit-box", "flex" ),
2440 ( "-webkit-inline-box", "inline-flex" ),
2441 ( "-webkit-flex", "flex" ),
2442 ( "-webkit-inline-flex", "inline-flex" ),
2443 ( "-webkit-min-content", "min-content" ),
2444 ( "-webkit-max-content", "max-content" ),
2445
2446 # Properties
2447 ( "-webkit-background-clip", "background-clip" ),
2448 ( "-webkit-background-origin", "background-origin" ),
2449 ( "-webkit-background-size", "background-size" ),
2450 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442451 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532452
2453 # Functions
2454 ( "-webkit-gradient", "gradient" ),
2455 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2456 ( "-webkit-linear-gradient", "linear-gradient" ),
2457 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2458 ( "-webkit-radial-gradient", "radial-gradient" ),
2459 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2460]
2461
dbeam1ec68ac2016-12-15 05:22:242462def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532463 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252464 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342465 documentation and iOS CSS for dom distiller
2466 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252467 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532468 results = []
dbeam070cfe62014-10-22 06:44:022469 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252470 black_list = (_EXCLUDED_PATHS +
2471 _TEST_CODE_EXCLUDED_PATHS +
2472 input_api.DEFAULT_BLACK_LIST +
2473 (r"^chrome/common/extensions/docs",
2474 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342475 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442476 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252477 r"^native_client_sdk"))
2478 file_filter = lambda f: input_api.FilterSourceFile(
2479 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532480 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2481 for line_num, line in fpath.ChangedContents():
2482 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022483 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532484 results.append(output_api.PresubmitError(
2485 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2486 (fpath.LocalPath(), line_num, deprecated_value, value)))
2487 return results
2488
mohan.reddyf21db962014-10-16 12:26:472489
dbeam070cfe62014-10-22 06:44:022490_DEPRECATED_JS = [
2491 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2492 ( "__defineGetter__", "Object.defineProperty" ),
2493 ( "__defineSetter__", "Object.defineProperty" ),
2494]
2495
dbeam1ec68ac2016-12-15 05:22:242496def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022497 """Make sure that we don't use deprecated JS in Chrome code."""
2498 results = []
2499 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2500 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2501 input_api.DEFAULT_BLACK_LIST)
2502 file_filter = lambda f: input_api.FilterSourceFile(
2503 f, white_list=file_inclusion_pattern, black_list=black_list)
2504 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2505 for lnum, line in fpath.ChangedContents():
2506 for (deprecated, replacement) in _DEPRECATED_JS:
2507 if deprecated in line:
2508 results.append(output_api.PresubmitError(
2509 "%s:%d: Use of deprecated JS %s, use %s instead" %
2510 (fpath.LocalPath(), lnum, deprecated, replacement)))
2511 return results
2512
dpapadd651231d82017-07-21 02:44:472513def _CheckForRiskyJsArrowFunction(line_number, line):
2514 if ' => ' in line:
2515 return "line %d, is using an => (arrow) function\n %s\n" % (
2516 line_number, line)
2517 return ''
2518
2519def _CheckForRiskyJsConstLet(input_api, line_number, line):
2520 if input_api.re.match('^\s*(const|let)\s', line):
2521 return "line %d, is using const/let keyword\n %s\n" % (
2522 line_number, line)
2523 return ''
dbeam070cfe62014-10-22 06:44:022524
dbeam1ec68ac2016-12-15 05:22:242525def _CheckForRiskyJsFeatures(input_api, output_api):
2526 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002527 # 'ui/webui/resources/cr_components are not allowed on ios'
2528 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572529 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002530 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472531 results = []
dbeam1ec68ac2016-12-15 05:22:242532 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472533 arrow_error_lines = []
2534 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242535 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472536 arrow_error_lines += filter(None, [
2537 _CheckForRiskyJsArrowFunction(lnum, line),
2538 ])
dbeam1ec68ac2016-12-15 05:22:242539
dpapadd651231d82017-07-21 02:44:472540 const_let_error_lines += filter(None, [
2541 _CheckForRiskyJsConstLet(input_api, lnum, line),
2542 ])
dbeam1ec68ac2016-12-15 05:22:242543
dpapadd651231d82017-07-21 02:44:472544 if arrow_error_lines:
2545 arrow_error_lines = map(
2546 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2547 results.append(
2548 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2549"""
2550Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242551%s
2552Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2553https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472554""" % f.LocalPath()
2555 ])))
dbeam1ec68ac2016-12-15 05:22:242556
dpapadd651231d82017-07-21 02:44:472557 if const_let_error_lines:
2558 const_let_error_lines = map(
2559 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2560 results.append(
2561 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2562"""
2563Use of const/let keywords detected in:
2564%s
2565Please ensure your code does not run on iOS9 because const/let is not fully
2566supported.
2567https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2568https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2569""" % f.LocalPath()
2570 ])))
2571
2572 return results
dbeam1ec68ac2016-12-15 05:22:242573
rlanday6802cf632017-05-30 17:48:362574def _CheckForRelativeIncludes(input_api, output_api):
2575 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2576 import sys
2577 original_sys_path = sys.path
2578 try:
2579 sys.path = sys.path + [input_api.os_path.join(
2580 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2581 from cpp_checker import CppChecker
2582 finally:
2583 # Restore sys.path to what it was before.
2584 sys.path = original_sys_path
2585
2586 bad_files = {}
2587 for f in input_api.AffectedFiles(include_deletes=False):
2588 if (f.LocalPath().startswith('third_party') and
2589 not f.LocalPath().startswith('third_party/WebKit') and
2590 not f.LocalPath().startswith('third_party\\WebKit')):
2591 continue
2592
2593 if not CppChecker.IsCppFile(f.LocalPath()):
2594 continue
2595
Vaclav Brozekd5de76a2018-03-17 07:57:502596 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:362597 if "#include" in line and "../" in line]
2598 if not relative_includes:
2599 continue
2600 bad_files[f.LocalPath()] = relative_includes
2601
2602 if not bad_files:
2603 return []
2604
2605 error_descriptions = []
2606 for file_path, bad_lines in bad_files.iteritems():
2607 error_description = file_path
2608 for line in bad_lines:
2609 error_description += '\n ' + line
2610 error_descriptions.append(error_description)
2611
2612 results = []
2613 results.append(output_api.PresubmitError(
2614 'You added one or more relative #include paths (including "../").\n'
2615 'These shouldn\'t be used because they can be used to include headers\n'
2616 'from code that\'s not correctly specified as a dependency in the\n'
2617 'relevant BUILD.gn file(s).',
2618 error_descriptions))
2619
2620 return results
2621
Takeshi Yoshinoe387aa32017-08-02 13:16:132622
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202623def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2624 if not isinstance(key, ast.Str):
2625 return 'Key at line %d must be a string literal' % key.lineno
2626 if not isinstance(value, ast.Dict):
2627 return 'Value at line %d must be a dict' % value.lineno
2628 if len(value.keys) != 1:
2629 return 'Dict at line %d must have single entry' % value.lineno
2630 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2631 return (
2632 'Entry at line %d must have a string literal \'filepath\' as key' %
2633 value.lineno)
2634 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132635
Takeshi Yoshinoe387aa32017-08-02 13:16:132636
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202637def _CheckWatchlistsEntrySyntax(key, value, ast):
2638 if not isinstance(key, ast.Str):
2639 return 'Key at line %d must be a string literal' % key.lineno
2640 if not isinstance(value, ast.List):
2641 return 'Value at line %d must be a list' % value.lineno
2642 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132643
Takeshi Yoshinoe387aa32017-08-02 13:16:132644
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202645def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2646 mismatch_template = (
2647 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2648 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132649
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202650 i = 0
2651 last_key = ''
2652 while True:
2653 if i >= len(wd_dict.keys):
2654 if i >= len(w_dict.keys):
2655 return None
2656 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2657 elif i >= len(w_dict.keys):
2658 return (
2659 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132660
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202661 wd_key = wd_dict.keys[i]
2662 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132663
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202664 result = _CheckWatchlistDefinitionsEntrySyntax(
2665 wd_key, wd_dict.values[i], ast)
2666 if result is not None:
2667 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132668
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202669 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2670 if result is not None:
2671 return 'Bad entry in WATCHLISTS dict: %s' % result
2672
2673 if wd_key.s != w_key.s:
2674 return mismatch_template % (
2675 '%s at line %d' % (wd_key.s, wd_key.lineno),
2676 '%s at line %d' % (w_key.s, w_key.lineno))
2677
2678 if wd_key.s < last_key:
2679 return (
2680 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2681 (wd_key.lineno, w_key.lineno))
2682 last_key = wd_key.s
2683
2684 i = i + 1
2685
2686
2687def _CheckWATCHLISTSSyntax(expression, ast):
2688 if not isinstance(expression, ast.Expression):
2689 return 'WATCHLISTS file must contain a valid expression'
2690 dictionary = expression.body
2691 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2692 return 'WATCHLISTS file must have single dict with exactly two entries'
2693
2694 first_key = dictionary.keys[0]
2695 first_value = dictionary.values[0]
2696 second_key = dictionary.keys[1]
2697 second_value = dictionary.values[1]
2698
2699 if (not isinstance(first_key, ast.Str) or
2700 first_key.s != 'WATCHLIST_DEFINITIONS' or
2701 not isinstance(first_value, ast.Dict)):
2702 return (
2703 'The first entry of the dict in WATCHLISTS file must be '
2704 'WATCHLIST_DEFINITIONS dict')
2705
2706 if (not isinstance(second_key, ast.Str) or
2707 second_key.s != 'WATCHLISTS' or
2708 not isinstance(second_value, ast.Dict)):
2709 return (
2710 'The second entry of the dict in WATCHLISTS file must be '
2711 'WATCHLISTS dict')
2712
2713 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132714
2715
2716def _CheckWATCHLISTS(input_api, output_api):
2717 for f in input_api.AffectedFiles(include_deletes=False):
2718 if f.LocalPath() == 'WATCHLISTS':
2719 contents = input_api.ReadFile(f, 'r')
2720
2721 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202722 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132723 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202724 # Get an AST tree for it and scan the tree for detailed style checking.
2725 expression = input_api.ast.parse(
2726 contents, filename='WATCHLISTS', mode='eval')
2727 except ValueError as e:
2728 return [output_api.PresubmitError(
2729 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2730 except SyntaxError as e:
2731 return [output_api.PresubmitError(
2732 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2733 except TypeError as e:
2734 return [output_api.PresubmitError(
2735 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132736
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202737 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2738 if result is not None:
2739 return [output_api.PresubmitError(result)]
2740 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132741
2742 return []
2743
2744
dgnaa68d5e2015-06-10 10:08:222745def _AndroidSpecificOnUploadChecks(input_api, output_api):
2746 """Groups checks that target android code."""
2747 results = []
dgnaa68d5e2015-06-10 10:08:222748 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222749 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292750 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062751 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2752 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422753 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182754 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222755 return results
2756
2757
[email protected]22c9bd72011-03-27 16:47:392758def _CommonChecks(input_api, output_api):
2759 """Checks common to both upload and commit."""
2760 results = []
2761 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382762 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542763 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:082764
2765 author = input_api.change.author_email
2766 if author and author not in _KNOWN_ROBOTS:
2767 results.extend(
2768 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
2769
[email protected]55459852011-08-10 15:17:192770 results.extend(
[email protected]760deea2013-12-10 19:33:492771 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:232772 results.extend(
2773 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542774 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182775 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522776 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222777 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442778 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592779 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062780 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122781 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182782 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222783 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302784 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492785 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032786 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492787 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442788 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272789 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072790 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542791 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442792 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392793 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552794 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042795 results.extend(
2796 input_api.canned_checks.CheckChangeHasNoTabs(
2797 input_api,
2798 output_api,
2799 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402800 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162801 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082802 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242803 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2804 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472805 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042806 results.extend(_CheckForIPCRules(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:142807 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232808 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432809 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402810 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152811 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172812 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502813 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242814 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362815 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132816 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432817 results.extend(input_api.RunTests(
2818 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242819
Vaclav Brozekcdc7defb2018-03-20 09:54:352820 for f in input_api.AffectedFiles():
2821 path, name = input_api.os_path.split(f.LocalPath())
2822 if name == 'PRESUBMIT.py':
2823 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
2824 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2825 input_api, output_api, full_path,
2826 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392827 return results
[email protected]1f7b4172010-01-28 01:17:342828
[email protected]b337cb5b2011-01-23 21:24:052829
[email protected]b8079ae4a2012-12-05 19:56:492830def _CheckPatchFiles(input_api, output_api):
2831 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2832 if f.LocalPath().endswith(('.orig', '.rej'))]
2833 if problems:
2834 return [output_api.PresubmitError(
2835 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032836 else:
2837 return []
[email protected]b8079ae4a2012-12-05 19:56:492838
2839
Kent Tamura5a8755d2017-06-29 23:37:072840def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212841 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2842 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2843 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072844 include_re = input_api.re.compile(
2845 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2846 extension_re = input_api.re.compile(r'\.[a-z]+$')
2847 errors = []
2848 for f in input_api.AffectedFiles():
2849 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2850 continue
2851 found_line_number = None
2852 found_macro = None
2853 for line_num, line in f.ChangedContents():
2854 match = macro_re.search(line)
2855 if match:
2856 found_line_number = line_num
2857 found_macro = match.group(2)
2858 break
2859 if not found_line_number:
2860 continue
2861
2862 found_include = False
2863 for line in f.NewContents():
2864 if include_re.search(line):
2865 found_include = True
2866 break
2867 if found_include:
2868 continue
2869
2870 if not f.LocalPath().endswith('.h'):
2871 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2872 try:
2873 content = input_api.ReadFile(primary_header_path, 'r')
2874 if include_re.search(content):
2875 continue
2876 except IOError:
2877 pass
2878 errors.append('%s:%d %s macro is used without including build/'
2879 'build_config.h.'
2880 % (f.LocalPath(), found_line_number, found_macro))
2881 if errors:
2882 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2883 return []
2884
2885
[email protected]b00342e7f2013-03-26 16:21:542886def _DidYouMeanOSMacro(bad_macro):
2887 try:
2888 return {'A': 'OS_ANDROID',
2889 'B': 'OS_BSD',
2890 'C': 'OS_CHROMEOS',
2891 'F': 'OS_FREEBSD',
2892 'L': 'OS_LINUX',
2893 'M': 'OS_MACOSX',
2894 'N': 'OS_NACL',
2895 'O': 'OS_OPENBSD',
2896 'P': 'OS_POSIX',
2897 'S': 'OS_SOLARIS',
2898 'W': 'OS_WIN'}[bad_macro[3].upper()]
2899 except KeyError:
2900 return ''
2901
2902
2903def _CheckForInvalidOSMacrosInFile(input_api, f):
2904 """Check for sensible looking, totally invalid OS macros."""
2905 preprocessor_statement = input_api.re.compile(r'^\s*#')
2906 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2907 results = []
2908 for lnum, line in f.ChangedContents():
2909 if preprocessor_statement.search(line):
2910 for match in os_macro.finditer(line):
2911 if not match.group(1) in _VALID_OS_MACROS:
2912 good = _DidYouMeanOSMacro(match.group(1))
2913 did_you_mean = ' (did you mean %s?)' % good if good else ''
2914 results.append(' %s:%d %s%s' % (f.LocalPath(),
2915 lnum,
2916 match.group(1),
2917 did_you_mean))
2918 return results
2919
2920
2921def _CheckForInvalidOSMacros(input_api, output_api):
2922 """Check all affected files for invalid OS macros."""
2923 bad_macros = []
2924 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472925 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542926 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2927
2928 if not bad_macros:
2929 return []
2930
2931 return [output_api.PresubmitError(
2932 'Possibly invalid OS macro[s] found. Please fix your code\n'
2933 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2934
lliabraa35bab3932014-10-01 12:16:442935
2936def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2937 """Check all affected files for invalid "if defined" macros."""
2938 ALWAYS_DEFINED_MACROS = (
2939 "TARGET_CPU_PPC",
2940 "TARGET_CPU_PPC64",
2941 "TARGET_CPU_68K",
2942 "TARGET_CPU_X86",
2943 "TARGET_CPU_ARM",
2944 "TARGET_CPU_MIPS",
2945 "TARGET_CPU_SPARC",
2946 "TARGET_CPU_ALPHA",
2947 "TARGET_IPHONE_SIMULATOR",
2948 "TARGET_OS_EMBEDDED",
2949 "TARGET_OS_IPHONE",
2950 "TARGET_OS_MAC",
2951 "TARGET_OS_UNIX",
2952 "TARGET_OS_WIN32",
2953 )
2954 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2955 results = []
2956 for lnum, line in f.ChangedContents():
2957 for match in ifdef_macro.finditer(line):
2958 if match.group(1) in ALWAYS_DEFINED_MACROS:
2959 always_defined = ' %s is always defined. ' % match.group(1)
2960 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2961 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2962 lnum,
2963 always_defined,
2964 did_you_mean))
2965 return results
2966
2967
2968def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2969 """Check all affected files for invalid "if defined" macros."""
2970 bad_macros = []
2971 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212972 if f.LocalPath().startswith('third_party/sqlite/'):
2973 continue
lliabraa35bab3932014-10-01 12:16:442974 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2975 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2976
2977 if not bad_macros:
2978 return []
2979
2980 return [output_api.PresubmitError(
2981 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2982 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2983 bad_macros)]
2984
2985
mlamouria82272622014-09-16 18:45:042986def _CheckForIPCRules(input_api, output_api):
2987 """Check for same IPC rules described in
2988 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2989 """
2990 base_pattern = r'IPC_ENUM_TRAITS\('
2991 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2992 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2993
2994 problems = []
2995 for f in input_api.AffectedSourceFiles(None):
2996 local_path = f.LocalPath()
2997 if not local_path.endswith('.h'):
2998 continue
2999 for line_number, line in f.ChangedContents():
3000 if inclusion_pattern.search(line) and not comment_pattern.search(line):
3001 problems.append(
3002 '%s:%d\n %s' % (local_path, line_number, line.strip()))
3003
3004 if problems:
3005 return [output_api.PresubmitPromptWarning(
3006 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
3007 else:
3008 return []
3009
[email protected]b00342e7f2013-03-26 16:21:543010
Daniel Bratell8ba52722018-03-02 16:06:143011def _CheckForIncludeGuards(input_api, output_api):
3012 """Check that header files have proper guards against multiple inclusion.
3013 If a file should not have such guards (and it probably should) then it
3014 should include the string "no-include-guard-because-multiply-included".
3015 """
3016 def is_header_file(f):
3017 return f.LocalPath().endswith('.h')
3018
3019 def replace_special_with_underscore(string):
3020 return input_api.re.sub(r'[\\/.-]', '_', string)
3021
3022 errors = []
3023
3024 for f in input_api.AffectedSourceFiles(is_header_file):
3025 guard_name = None
3026 guard_line_number = None
3027 seen_guard_end = False
3028
3029 file_with_path = input_api.os_path.normpath(f.LocalPath())
3030 base_file_name = input_api.os_path.splitext(
3031 input_api.os_path.basename(file_with_path))[0]
3032 upper_base_file_name = base_file_name.upper()
3033
3034 expected_guard = replace_special_with_underscore(
3035 file_with_path.upper() + '_')
3036 expected_guard_if_blink = base_file_name + '_h'
3037
3038 # For "path/elem/file_name.h" we should really only accept
3039 # PATH_ELEM_FILE_NAME_H_ per coding style or, if Blink,
3040 # file_name_h. Unfortunately there are too many (1000+) files
3041 # with slight deviations from the coding style. Since the most
3042 # important part is that the include guard is there, and that it's
3043 # unique, not the name, this check is forgiving for existing files.
3044 #
3045 # As code becomes more uniform, this could be made stricter.
3046
3047 guard_name_pattern_list = [
3048 # Anything with the right suffix (maybe with an extra _).
3049 r'\w+_H__?',
3050
3051 # To cover include guards with Blink style.
3052 r'\w+_h',
3053
3054 # Anything including the uppercase name of the file.
3055 r'\w*' + input_api.re.escape(replace_special_with_underscore(
3056 upper_base_file_name)) + r'\w*',
3057 ]
3058 guard_name_pattern = '|'.join(guard_name_pattern_list)
3059 guard_pattern = input_api.re.compile(
3060 r'#ifndef\s+(' + guard_name_pattern + ')')
3061
3062 for line_number, line in enumerate(f.NewContents()):
3063 if 'no-include-guard-because-multiply-included' in line:
3064 guard_name = 'DUMMY' # To not trigger check outside the loop.
3065 break
3066
3067 if guard_name is None:
3068 match = guard_pattern.match(line)
3069 if match:
3070 guard_name = match.group(1)
3071 guard_line_number = line_number
3072
3073 # We allow existing files to use slightly wrong include
3074 # guards, but new files should get it right.
3075 if not f.OldContents():
3076 is_in_blink = file_with_path.startswith(input_api.os_path.join(
3077 'third_party', 'WebKit'))
3078 if not (guard_name == expected_guard or
3079 is_in_blink and guard_name == expected_guard_if_blink):
3080 if is_in_blink:
3081 expected_text = "%s or %s" % (expected_guard,
3082 expected_guard_if_blink)
3083 else:
3084 expected_text = expected_guard
3085 errors.append(output_api.PresubmitPromptWarning(
3086 'Header using the wrong include guard name %s' % guard_name,
3087 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Daniel Bratell00e1b9bc2018-03-12 13:11:123088 'Expected: %r\nFound: %r' % (expected_text, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:143089 else:
3090 # The line after #ifndef should have a #define of the same name.
3091 if line_number == guard_line_number + 1:
3092 expected_line = '#define %s' % guard_name
3093 if line != expected_line:
3094 errors.append(output_api.PresubmitPromptWarning(
3095 'Missing "%s" for include guard' % expected_line,
3096 ['%s:%d' % (f.LocalPath(), line_number + 1)],
3097 'Expected: %r\nGot: %r' % (expected_line, line)))
3098
3099 if not seen_guard_end and line == '#endif // %s' % guard_name:
3100 seen_guard_end = True
3101 elif seen_guard_end:
3102 if line.strip() != '':
3103 errors.append(output_api.PresubmitPromptWarning(
3104 'Include guard %s not covering the whole file' % (
3105 guard_name), [f.LocalPath()]))
3106 break # Nothing else to check and enough to warn once.
3107
3108 if guard_name is None:
3109 errors.append(output_api.PresubmitPromptWarning(
3110 'Missing include guard %s' % expected_guard,
3111 [f.LocalPath()],
3112 'Missing include guard in %s\n'
3113 'Recommended name: %s\n'
3114 'This check can be disabled by having the string\n'
3115 'no-include-guard-because-multiply-included in the header.' %
3116 (f.LocalPath(), expected_guard)))
3117
3118 return errors
3119
3120
mostynbb639aca52015-01-07 20:31:233121def _CheckForWindowsLineEndings(input_api, output_api):
3122 """Check source code and known ascii text files for Windows style line
3123 endings.
3124 """
earthdok1b5e0ee2015-03-10 15:19:103125 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:233126
3127 file_inclusion_pattern = (
3128 known_text_files,
3129 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3130 )
3131
mostynbb639aca52015-01-07 20:31:233132 problems = []
Andrew Grieve933d12e2017-10-30 20:22:533133 source_file_filter = lambda f: input_api.FilterSourceFile(
3134 f, white_list=file_inclusion_pattern, black_list=None)
3135 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:503136 include_file = False
3137 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:233138 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:503139 include_file = True
3140 if include_file:
3141 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:233142
3143 if problems:
3144 return [output_api.PresubmitPromptWarning('Are you sure that you want '
3145 'these files to contain Windows style line endings?\n' +
3146 '\n'.join(problems))]
3147
3148 return []
3149
3150
Vaclav Brozekd5de76a2018-03-17 07:57:503151def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:133152 """Checks that all source files use SYSLOG properly."""
3153 syslog_files = []
3154 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:563155 for line_number, line in f.ChangedContents():
3156 if 'SYSLOG' in line:
3157 syslog_files.append(f.LocalPath() + ':' + str(line_number))
3158
pastarmovj89f7ee12016-09-20 14:58:133159 if syslog_files:
3160 return [output_api.PresubmitPromptWarning(
3161 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
3162 ' calls.\nFiles to check:\n', items=syslog_files)]
3163 return []
3164
3165
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193166def _CheckCrbugLinksHaveHttps(input_api, output_api):
Miguel Casas68bdb652017-12-19 16:29:093167 """Checks that crbug(.com) links are correctly prefixed by https://,
3168 unless they come in the accepted form TODO(crbug.com/...)
3169 """
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193170 white_list = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3171 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS)
3172 sources = lambda f: input_api.FilterSourceFile(
3173 f, white_list=white_list, black_list=black_list)
3174
3175 pattern = input_api.re.compile(r'//.*(?<!:\/\/)crbug[.com]*')
Miguel Casas68bdb652017-12-19 16:29:093176 accepted_pattern = input_api.re.compile(r'//.*TODO\(crbug[.com]*');
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193177 problems = []
3178 for f in input_api.AffectedSourceFiles(sources):
3179 for line_num, line in f.ChangedContents():
Miguel Casas68bdb652017-12-19 16:29:093180 if pattern.search(line) and not accepted_pattern.search(line):
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193181 problems.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
3182
3183 if problems:
3184 return [output_api.PresubmitPromptWarning(
3185 'Found unprefixed crbug.com URL(s), consider prepending https://\n'+
3186 '\n'.join(problems))]
3187 return []
3188
3189
[email protected]1f7b4172010-01-28 01:17:343190def CheckChangeOnUpload(input_api, output_api):
3191 results = []
3192 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:473193 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:283194 results.extend(
jam93a6ee792017-02-08 23:59:223195 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:193196 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:223197 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:133198 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:163199 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193200 results.extend(_CheckCrbugLinksHaveHttps(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:533201 results.extend(_CheckUniquePtr(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543202 return results
[email protected]ca8d19842009-02-19 16:33:123203
3204
[email protected]1bfb8322014-04-23 01:02:413205def GetTryServerMasterForBot(bot):
3206 """Returns the Try Server master for the given bot.
3207
[email protected]0bb112362014-07-26 04:38:323208 It tries to guess the master from the bot name, but may still fail
3209 and return None. There is no longer a default master.
3210 """
3211 # Potentially ambiguous bot names are listed explicitly.
3212 master_map = {
tandriie5587792016-07-14 00:34:503213 'chromium_presubmit': 'master.tryserver.chromium.linux',
3214 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:413215 }
[email protected]0bb112362014-07-26 04:38:323216 master = master_map.get(bot)
3217 if not master:
wnwen4fbaab82016-05-25 12:54:363218 if 'android' in bot:
tandriie5587792016-07-14 00:34:503219 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:363220 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:503221 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:323222 elif 'win' in bot:
tandriie5587792016-07-14 00:34:503223 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:323224 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:503225 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:323226 return master
[email protected]1bfb8322014-04-23 01:02:413227
3228
[email protected]ca8d19842009-02-19 16:33:123229def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:543230 results = []
[email protected]1f7b4172010-01-28 01:17:343231 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543232 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:273233 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:343234 input_api,
3235 output_api,
[email protected]2fdd1f362013-01-16 03:56:033236 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:273237
jam93a6ee792017-02-08 23:59:223238 results.extend(
3239 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:543240 results.extend(input_api.canned_checks.CheckChangeHasBugField(
3241 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:413242 results.extend(input_api.canned_checks.CheckChangeHasDescription(
3243 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543244 return results