blob: 2b2ab5b13f603949676076816b1671f7947c82f2 [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,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41340 (
341 r'^third_party[\\\/]abseil-cpp[\\\/].*',
342 ),
jame2d1a952016-04-02 00:27:10343 ),
fdorayc4ac18d2017-05-01 21:39:59344 (
gabd52c912a2017-05-11 04:15:59345 'base::SequenceChecker',
346 (
347 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
348 ),
349 False,
350 (),
351 ),
352 (
353 'base::ThreadChecker',
354 (
355 'Consider using THREAD_CHECKER macros instead of the class directly.',
356 ),
357 False,
358 (),
359 ),
dbeamb6f4fde2017-06-15 04:03:06360 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06361 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
362 (
363 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
364 'deprecated (http://crbug.com/634507). Please avoid converting away',
365 'from the Time types in Chromium code, especially if any math is',
366 'being done on time values. For interfacing with platform/library',
367 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
368 'type converter methods instead. For faking TimeXXX values (for unit',
369 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
370 'other use cases, please contact base/time/OWNERS.',
371 ),
372 False,
373 (),
374 ),
375 (
dbeamb6f4fde2017-06-15 04:03:06376 'CallJavascriptFunctionUnsafe',
377 (
378 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
379 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
380 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
381 ),
382 False,
383 (
384 r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$',
385 r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$',
386 r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$',
387 ),
388 ),
dskiba1474c2bfd62017-07-20 02:19:24389 (
390 'leveldb::DB::Open',
391 (
392 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
393 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
394 "Chrome's tracing, making their memory usage visible.",
395 ),
396 True,
397 (
398 r'^third_party/leveldatabase/.*\.(cc|h)$',
399 ),
Gabriel Charette0592c3a2017-07-26 12:02:04400 ),
401 (
Chris Mumfordc38afb62017-10-09 17:55:08402 'leveldb::NewMemEnv',
403 (
404 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
405 'third_party/leveldatabase/leveldb_chrome.h.',
406 ),
407 True,
408 (
409 r'^third_party/leveldatabase/.*\.(cc|h)$',
410 ),
411 ),
412 (
Gabriel Charetted9839bc2017-07-29 14:17:47413 'MessageLoop::QuitWhenIdleClosure',
Gabriel Charette0592c3a2017-07-26 12:02:04414 (
Peter Kasting9e7ccfa52018-02-06 00:01:20415 'MessageLoop::QuitWhenIdleClosure is deprecated. Please use a',
416 'QuitWhenIdleClosure obtained from a specific RunLoop instance.',
Gabriel Charette0592c3a2017-07-26 12:02:04417 ),
Peter Kasting9e7ccfa52018-02-06 00:01:20418 False,
Gabriel Charette0592c3a2017-07-26 12:02:04419 (),
Gabriel Charetted9839bc2017-07-29 14:17:47420 ),
421 (
422 'RunLoop::QuitCurrent',
423 (
Robert Liao64b7ab22017-08-04 23:03:43424 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
425 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47426 ),
427 True,
428 (),
Gabriel Charettea44975052017-08-21 23:14:04429 ),
430 (
431 'base::ScopedMockTimeMessageLoopTaskRunner',
432 (
433 'ScopedMockTimeMessageLoopTaskRunner is deprecated.',
434 ),
435 True,
436 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57437 ),
438 (
439 r'std::regex',
440 (
441 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02442 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57443 ),
444 True,
445 (),
Francois Doray43670e32017-09-27 12:40:38446 ),
447 (
448 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
449 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
450 (
451 'Use the new API in base/threading/thread_restrictions.h.',
452 ),
453 True,
454 (),
455 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38456 (
457 r'/\bbase::Bind\(',
458 (
Gabriel Charette147335ea2018-03-22 15:59:19459 'Please consider using base::Bind{Once,Repeating} instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02460 'of base::Bind. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38461 ),
462 False,
463 (),
464 ),
465 (
466 r'/\bbase::Callback<',
467 (
Gabriel Charette147335ea2018-03-22 15:59:19468 'Please consider using base::{Once,Repeating}Callback instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02469 'of base::Callback. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38470 ),
471 False,
472 (),
473 ),
474 (
475 r'/\bbase::Closure\b',
476 (
Gabriel Charette147335ea2018-03-22 15:59:19477 'Please consider using base::{Once,Repeating}Closure instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02478 'of base::Closure. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38479 ),
480 False,
481 (),
482 ),
Victor Costan3653df62018-02-08 21:38:16483 (
Gabriel Charette147335ea2018-03-22 15:59:19484 r'RunMessageLoop',
485 (
486 'RunMessageLoop is deprecated, use RunLoop instead.',
487 ),
488 False,
489 (),
490 ),
491 (
492 r'RunThisRunLoop',
493 (
494 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
495 ),
496 False,
497 (),
498 ),
499 (
500 r'RunAllPendingInMessageLoop()',
501 (
502 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
503 "if you're convinced you need this.",
504 ),
505 False,
506 (),
507 ),
508 (
509 r'RunAllPendingInMessageLoop(BrowserThread',
510 (
511 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
512 'BrowserThread::UI, TestBrowserThreadBundle::RunIOThreadUntilIdle',
513 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
514 'async events instead of flushing threads.',
515 ),
516 False,
517 (),
518 ),
519 (
520 r'MessageLoopRunner',
521 (
522 'MessageLoopRunner is deprecated, use RunLoop instead.',
523 ),
524 False,
525 (),
526 ),
527 (
528 r'GetDeferredQuitTaskForRunLoop',
529 (
530 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
531 "gab@ if you found a use case where this is the only solution.",
532 ),
533 False,
534 (),
535 ),
536 (
Victor Costan3653df62018-02-08 21:38:16537 'sqlite3_initialize',
538 (
539 'Instead of sqlite3_initialize, depend on //sql, ',
540 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
541 ),
542 True,
543 (
544 r'^sql/initialization\.(cc|h)$',
545 r'^third_party/sqlite/.*\.(c|cc|h)$',
546 ),
547 ),
Matt Menke7f520a82018-03-28 21:38:37548 (
549 'net::URLFetcher',
550 (
551 'net::URLFetcher should no longer be used in content embedders. ',
552 'Instead, use network::SimpleURLLoader instead, which supports ',
553 'an out-of-process network stack. ',
554 'net::URLFetcher may still be used in binaries that do not embed',
555 'content.',
556 ),
Matt Menke59716d02018-04-05 12:45:53557 False,
Matt Menke7f520a82018-03-28 21:38:37558 (
559 r'^ios[\\\/].*\.(cc|h)$',
560 r'.*[\\\/]ios[\\\/].*\.(cc|h)$',
561 r'.*_ios\.(cc|h)$',
562 r'^net[\\\/].*\.(cc|h)$',
563 r'.*[\\\/]tools[\\\/].*\.(cc|h)$',
564 ),
565 ),
[email protected]127f18ec2012-06-16 05:05:59566)
567
wnwenbdc444e2016-05-25 13:44:15568
mlamouria82272622014-09-16 18:45:04569_IPC_ENUM_TRAITS_DEPRECATED = (
570 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50571 'See http://www.chromium.org/Home/chromium-security/education/'
572 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:04573
Shenghua Zhangbfaa38b82017-11-16 21:58:02574_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
575 r".*[\\\/]BuildHooksAndroidImpl\.java",
576 r".*[\\\/]LicenseContentProvider\.java",
577]
[email protected]127f18ec2012-06-16 05:05:59578
Sean Kau46e29bc2017-08-28 16:31:16579# These paths contain test data and other known invalid JSON files.
580_KNOWN_INVALID_JSON_FILE_PATTERNS = [
581 r'test[\\\/]data[\\\/]',
582 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
583 r'^third_party[\\\/]protobuf[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16584 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Sean Kau46e29bc2017-08-28 16:31:16585]
586
587
[email protected]b00342e7f2013-03-26 16:21:54588_VALID_OS_MACROS = (
589 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08590 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54591 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:12592 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:54593 'OS_BSD',
594 'OS_CAT', # For testing.
595 'OS_CHROMEOS',
596 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37597 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54598 'OS_IOS',
599 'OS_LINUX',
600 'OS_MACOSX',
601 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21602 'OS_NACL_NONSFI',
603 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12604 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54605 'OS_OPENBSD',
606 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37607 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54608 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54609 'OS_WIN',
610)
611
612
agrievef32bcc72016-04-04 14:57:40613_ANDROID_SPECIFIC_PYDEPS_FILES = [
614 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04615 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58616 'build/secondary/third_party/android_platform/'
617 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19618 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40619]
620
wnwenbdc444e2016-05-25 13:44:15621
agrievef32bcc72016-04-04 14:57:40622_GENERIC_PYDEPS_FILES = [
John Chencde89192018-01-27 21:18:40623 'chrome/test/chromedriver/test/run_py_tests.pydeps',
agrievef32bcc72016-04-04 14:57:40624]
625
wnwenbdc444e2016-05-25 13:44:15626
agrievef32bcc72016-04-04 14:57:40627_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
628
629
Eric Boren6fd2b932018-01-25 15:05:08630# Bypass the AUTHORS check for these accounts.
631_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:29632 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
633 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
634 'fuchsia-sdk', 'nacl', 'pdfium', 'skia', 'src-internal', 'webrtc')
635 ) | set('%[email protected]' % s for s in ('findit-for-me',))
Eric Boren6fd2b932018-01-25 15:05:08636
637
[email protected]55459852011-08-10 15:17:19638def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
639 """Attempts to prevent use of functions intended only for testing in
640 non-testing code. For now this is just a best-effort implementation
641 that ignores header files and may have some false positives. A
642 better implementation would probably need a proper C++ parser.
643 """
644 # We only scan .cc files and the like, as the declaration of
645 # for-testing functions in header files are hard to distinguish from
646 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44647 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19648
jochenc0d4808c2015-07-27 09:25:42649 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19650 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09651 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19652 exclusion_pattern = input_api.re.compile(
653 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
654 base_function_pattern, base_function_pattern))
655
656 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44657 black_list = (_EXCLUDED_PATHS +
658 _TEST_CODE_EXCLUDED_PATHS +
659 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19660 return input_api.FilterSourceFile(
661 affected_file,
662 white_list=(file_inclusion_pattern, ),
663 black_list=black_list)
664
665 problems = []
666 for f in input_api.AffectedSourceFiles(FilterFile):
667 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24668 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03669 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46670 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03671 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19672 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03673 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19674
675 if problems:
[email protected]f7051d52013-04-02 18:31:42676 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03677 else:
678 return []
[email protected]55459852011-08-10 15:17:19679
680
Vaclav Brozek7dbc28c2018-03-27 08:35:23681def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
682 """This is a simplified version of
683 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
684 """
685 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
686 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
687 name_pattern = r'ForTest(s|ing)?'
688 # Describes an occurrence of "ForTest*" inside a // comment.
689 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
690 # Catch calls.
691 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
692 # Ignore definitions. (Comments are ignored separately.)
693 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
694
695 problems = []
696 sources = lambda x: input_api.FilterSourceFile(
697 x,
698 black_list=(('(?i).*test', r'.*\/junit\/')
699 + input_api.DEFAULT_BLACK_LIST),
700 white_list=(r'.*\.java$',)
701 )
702 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
703 local_path = f.LocalPath()
704 is_inside_javadoc = False
705 for line_number, line in f.ChangedContents():
706 if is_inside_javadoc and javadoc_end_re.search(line):
707 is_inside_javadoc = False
708 if not is_inside_javadoc and javadoc_start_re.search(line):
709 is_inside_javadoc = True
710 if is_inside_javadoc:
711 continue
712 if (inclusion_re.search(line) and
713 not comment_re.search(line) and
714 not exclusion_re.search(line)):
715 problems.append(
716 '%s:%d\n %s' % (local_path, line_number, line.strip()))
717
718 if problems:
719 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
720 else:
721 return []
722
723
[email protected]10689ca2011-09-02 02:31:54724def _CheckNoIOStreamInHeaders(input_api, output_api):
725 """Checks to make sure no .h files include <iostream>."""
726 files = []
727 pattern = input_api.re.compile(r'^#include\s*<iostream>',
728 input_api.re.MULTILINE)
729 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
730 if not f.LocalPath().endswith('.h'):
731 continue
732 contents = input_api.ReadFile(f)
733 if pattern.search(contents):
734 files.append(f)
735
736 if len(files):
yolandyandaabc6d2016-04-18 18:29:39737 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06738 'Do not #include <iostream> in header files, since it inserts static '
739 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54740 '#include <ostream>. See http://crbug.com/94794',
741 files) ]
742 return []
743
744
[email protected]72df4e782012-06-21 16:28:18745def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52746 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18747 problems = []
748 for f in input_api.AffectedFiles():
749 if (not f.LocalPath().endswith(('.cc', '.mm'))):
750 continue
751
752 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04753 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18754 problems.append(' %s:%d' % (f.LocalPath(), line_num))
755
756 if not problems:
757 return []
758 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
759 '\n'.join(problems))]
760
761
danakj61c1aa22015-10-26 19:55:52762def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57763 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52764 errors = []
765 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
766 input_api.re.MULTILINE)
767 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
768 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
769 continue
770 for lnum, line in f.ChangedContents():
771 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17772 errors.append(output_api.PresubmitError(
773 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57774 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17775 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52776 return errors
777
778
mcasasb7440c282015-02-04 14:52:19779def _FindHistogramNameInLine(histogram_name, line):
780 """Tries to find a histogram name or prefix in a line."""
781 if not "affected-histogram" in line:
782 return histogram_name in line
783 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
784 # the histogram_name.
785 if not '"' in line:
786 return False
787 histogram_prefix = line.split('\"')[1]
788 return histogram_prefix in histogram_name
789
790
791def _CheckUmaHistogramChanges(input_api, output_api):
792 """Check that UMA histogram names in touched lines can still be found in other
793 lines of the patch or in histograms.xml. Note that this check would not catch
794 the reverse: changes in histograms.xml not matched in the code itself."""
795 touched_histograms = []
796 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:47797 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
798 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
799 name_pattern = r'"(.*?)"'
800 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
801 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
802 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
803 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
804 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:17805 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:19806 for f in input_api.AffectedFiles():
807 # If histograms.xml itself is modified, keep the modified lines for later.
808 if f.LocalPath().endswith(('histograms.xml')):
809 histograms_xml_modifications = f.ChangedContents()
810 continue
Vaclav Brozekbdac817c2018-03-24 06:30:47811 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
812 single_line_re = single_line_c_re
813 split_line_prefix_re = split_line_c_prefix_re
814 elif f.LocalPath().endswith(('java')):
815 single_line_re = single_line_java_re
816 split_line_prefix_re = split_line_java_prefix_re
817 else:
mcasasb7440c282015-02-04 14:52:19818 continue
819 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:17820 if last_line_matched_prefix:
821 suffix_found = split_line_suffix_re.search(line)
822 if suffix_found :
823 touched_histograms.append([suffix_found.group(1), f, line_num])
824 last_line_matched_prefix = False
825 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:06826 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:19827 if found:
828 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:17829 continue
830 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:19831
832 # Search for the touched histogram names in the local modifications to
833 # histograms.xml, and, if not found, on the base histograms.xml file.
834 unmatched_histograms = []
835 for histogram_info in touched_histograms:
836 histogram_name_found = False
837 for line_num, line in histograms_xml_modifications:
838 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
839 if histogram_name_found:
840 break
841 if not histogram_name_found:
842 unmatched_histograms.append(histogram_info)
843
eromanb90c82e7e32015-04-01 15:13:49844 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19845 problems = []
846 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49847 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19848 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45849 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19850 histogram_name_found = False
851 for line in histograms_xml:
852 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
853 if histogram_name_found:
854 break
855 if not histogram_name_found:
856 problems.append(' [%s:%d] %s' %
857 (f.LocalPath(), line_num, histogram_name))
858
859 if not problems:
860 return []
861 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
862 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49863 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19864
wnwenbdc444e2016-05-25 13:44:15865
yolandyandaabc6d2016-04-18 18:29:39866def _CheckFlakyTestUsage(input_api, output_api):
867 """Check that FlakyTest annotation is our own instead of the android one"""
868 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
869 files = []
870 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
871 if f.LocalPath().endswith('Test.java'):
872 if pattern.search(input_api.ReadFile(f)):
873 files.append(f)
874 if len(files):
875 return [output_api.PresubmitError(
876 'Use org.chromium.base.test.util.FlakyTest instead of '
877 'android.test.FlakyTest',
878 files)]
879 return []
mcasasb7440c282015-02-04 14:52:19880
wnwenbdc444e2016-05-25 13:44:15881
[email protected]8ea5d4b2011-09-13 21:49:22882def _CheckNoNewWStrings(input_api, output_api):
883 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27884 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22885 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20886 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57887 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34888 '/win/' in f.LocalPath() or
889 'chrome_elf' in f.LocalPath() or
890 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20891 continue
[email protected]8ea5d4b2011-09-13 21:49:22892
[email protected]a11dbe9b2012-08-07 01:32:58893 allowWString = False
[email protected]b5c24292011-11-28 14:38:20894 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58895 if 'presubmit: allow wstring' in line:
896 allowWString = True
897 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27898 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58899 allowWString = False
900 else:
901 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22902
[email protected]55463aa62011-10-12 00:48:27903 if not problems:
904 return []
905 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58906 ' If you are calling a cross-platform API that accepts a wstring, '
907 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27908 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22909
910
[email protected]2a8ac9c2011-10-19 17:20:44911def _CheckNoDEPSGIT(input_api, output_api):
912 """Make sure .DEPS.git is never modified manually."""
913 if any(f.LocalPath().endswith('.DEPS.git') for f in
914 input_api.AffectedFiles()):
915 return [output_api.PresubmitError(
916 'Never commit changes to .DEPS.git. This file is maintained by an\n'
917 'automated system based on what\'s in DEPS and your changes will be\n'
918 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50919 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
920 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:44921 'for more information')]
922 return []
923
924
tandriief664692014-09-23 14:51:47925def _CheckValidHostsInDEPS(input_api, output_api):
926 """Checks that DEPS file deps are from allowed_hosts."""
927 # Run only if DEPS file has been modified to annoy fewer bystanders.
928 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
929 return []
930 # Outsource work to gclient verify
931 try:
932 input_api.subprocess.check_output(['gclient', 'verify'])
933 return []
934 except input_api.subprocess.CalledProcessError, error:
935 return [output_api.PresubmitError(
936 'DEPS file must have only git dependencies.',
937 long_text=error.output)]
938
939
[email protected]127f18ec2012-06-16 05:05:59940def _CheckNoBannedFunctions(input_api, output_api):
941 """Make sure that banned functions are not used."""
942 warnings = []
943 errors = []
944
wnwenbdc444e2016-05-25 13:44:15945 def IsBlacklisted(affected_file, blacklist):
946 local_path = affected_file.LocalPath()
947 for item in blacklist:
948 if input_api.re.match(item, local_path):
949 return True
950 return False
951
Sylvain Defresnea8b73d252018-02-28 15:45:54952 def IsIosObcjFile(affected_file):
953 local_path = affected_file.LocalPath()
954 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
955 return False
956 basename = input_api.os_path.basename(local_path)
957 if 'ios' in basename.split('_'):
958 return True
959 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
960 if sep and 'ios' in local_path.split(sep):
961 return True
962 return False
963
wnwenbdc444e2016-05-25 13:44:15964 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
965 matched = False
966 if func_name[0:1] == '/':
967 regex = func_name[1:]
968 if input_api.re.search(regex, line):
969 matched = True
970 elif func_name in line:
dchenge07de812016-06-20 19:27:17971 matched = True
wnwenbdc444e2016-05-25 13:44:15972 if matched:
dchenge07de812016-06-20 19:27:17973 problems = warnings
wnwenbdc444e2016-05-25 13:44:15974 if error:
dchenge07de812016-06-20 19:27:17975 problems = errors
wnwenbdc444e2016-05-25 13:44:15976 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
977 for message_line in message:
978 problems.append(' %s' % message_line)
979
Eric Stevensona9a980972017-09-23 00:04:41980 file_filter = lambda f: f.LocalPath().endswith(('.java'))
981 for f in input_api.AffectedFiles(file_filter=file_filter):
982 for line_num, line in f.ChangedContents():
983 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
984 CheckForMatch(f, line_num, line, func_name, message, error)
985
[email protected]127f18ec2012-06-16 05:05:59986 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
987 for f in input_api.AffectedFiles(file_filter=file_filter):
988 for line_num, line in f.ChangedContents():
989 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15990 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59991
Sylvain Defresnea8b73d252018-02-28 15:45:54992 for f in input_api.AffectedFiles(file_filter=IsIosObcjFile):
993 for line_num, line in f.ChangedContents():
994 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
995 CheckForMatch(f, line_num, line, func_name, message, error)
996
[email protected]127f18ec2012-06-16 05:05:59997 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
998 for f in input_api.AffectedFiles(file_filter=file_filter):
999 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491000 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491001 if IsBlacklisted(f, excluded_paths):
1002 continue
wnwenbdc444e2016-05-25 13:44:151003 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591004
1005 result = []
1006 if (warnings):
1007 result.append(output_api.PresubmitPromptWarning(
1008 'Banned functions were used.\n' + '\n'.join(warnings)))
1009 if (errors):
1010 result.append(output_api.PresubmitError(
1011 'Banned functions were used.\n' + '\n'.join(errors)))
1012 return result
1013
1014
[email protected]6c063c62012-07-11 19:11:061015def _CheckNoPragmaOnce(input_api, output_api):
1016 """Make sure that banned functions are not used."""
1017 files = []
1018 pattern = input_api.re.compile(r'^#pragma\s+once',
1019 input_api.re.MULTILINE)
1020 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1021 if not f.LocalPath().endswith('.h'):
1022 continue
1023 contents = input_api.ReadFile(f)
1024 if pattern.search(contents):
1025 files.append(f)
1026
1027 if files:
1028 return [output_api.PresubmitError(
1029 'Do not use #pragma once in header files.\n'
1030 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1031 files)]
1032 return []
1033
[email protected]127f18ec2012-06-16 05:05:591034
[email protected]e7479052012-09-19 00:26:121035def _CheckNoTrinaryTrueFalse(input_api, output_api):
1036 """Checks to make sure we don't introduce use of foo ? true : false."""
1037 problems = []
1038 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1039 for f in input_api.AffectedFiles():
1040 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1041 continue
1042
1043 for line_num, line in f.ChangedContents():
1044 if pattern.match(line):
1045 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1046
1047 if not problems:
1048 return []
1049 return [output_api.PresubmitPromptWarning(
1050 'Please consider avoiding the "? true : false" pattern if possible.\n' +
1051 '\n'.join(problems))]
1052
1053
[email protected]55f9f382012-07-31 11:02:181054def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:281055 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:181056 change. Breaking - rules is an error, breaking ! rules is a
1057 warning.
1058 """
mohan.reddyf21db962014-10-16 12:26:471059 import sys
[email protected]55f9f382012-07-31 11:02:181060 # We need to wait until we have an input_api object and use this
1061 # roundabout construct to import checkdeps because this file is
1062 # eval-ed and thus doesn't have __file__.
1063 original_sys_path = sys.path
1064 try:
1065 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:471066 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:181067 import checkdeps
1068 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:241069 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:281070 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:181071 from rules import Rule
1072 finally:
1073 # Restore sys.path to what it was before.
1074 sys.path = original_sys_path
1075
1076 added_includes = []
rhalavati08acd232017-04-03 07:23:281077 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:241078 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:181079 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:281080 if CppChecker.IsCppFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501081 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081082 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:281083 elif ProtoChecker.IsProtoFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501084 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081085 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:241086 elif JavaChecker.IsJavaFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501087 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081088 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:181089
[email protected]26385172013-05-09 23:11:351090 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181091
1092 error_descriptions = []
1093 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:281094 error_subjects = set()
1095 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:181096 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
1097 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:081098 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181099 description_with_path = '%s\n %s' % (path, rule_description)
1100 if rule_type == Rule.DISALLOW:
1101 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281102 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:181103 else:
1104 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281105 warning_subjects.add("#includes")
1106
1107 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
1108 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:081109 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:281110 description_with_path = '%s\n %s' % (path, rule_description)
1111 if rule_type == Rule.DISALLOW:
1112 error_descriptions.append(description_with_path)
1113 error_subjects.add("imports")
1114 else:
1115 warning_descriptions.append(description_with_path)
1116 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:181117
Jinsuk Kim5a092672017-10-24 22:42:241118 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:021119 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:081120 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:241121 description_with_path = '%s\n %s' % (path, rule_description)
1122 if rule_type == Rule.DISALLOW:
1123 error_descriptions.append(description_with_path)
1124 error_subjects.add("imports")
1125 else:
1126 warning_descriptions.append(description_with_path)
1127 warning_subjects.add("imports")
1128
[email protected]55f9f382012-07-31 11:02:181129 results = []
1130 if error_descriptions:
1131 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:281132 'You added one or more %s that violate checkdeps rules.'
1133 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:181134 error_descriptions))
1135 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:421136 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:281137 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:181138 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:281139 '%s? See relevant DEPS file(s) for details and contacts.' %
1140 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:181141 warning_descriptions))
1142 return results
1143
1144
[email protected]fbcafe5a2012-08-08 15:31:221145def _CheckFilePermissions(input_api, output_api):
1146 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:151147 if input_api.platform == 'win32':
1148 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:291149 checkperms_tool = input_api.os_path.join(
1150 input_api.PresubmitLocalPath(),
1151 'tools', 'checkperms', 'checkperms.py')
1152 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:471153 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:391154 with input_api.CreateTemporaryFile() as file_list:
1155 for f in input_api.AffectedFiles():
1156 # checkperms.py file/directory arguments must be relative to the
1157 # repository.
1158 file_list.write(f.LocalPath() + '\n')
1159 file_list.close()
1160 args += ['--file-list', file_list.name]
1161 try:
1162 input_api.subprocess.check_output(args)
1163 return []
1164 except input_api.subprocess.CalledProcessError as error:
1165 return [output_api.PresubmitError(
1166 'checkperms.py failed:',
1167 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:221168
1169
robertocn832f5992017-01-04 19:01:301170def _CheckTeamTags(input_api, output_api):
1171 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
1172 checkteamtags_tool = input_api.os_path.join(
1173 input_api.PresubmitLocalPath(),
1174 'tools', 'checkteamtags', 'checkteamtags.py')
1175 args = [input_api.python_executable, checkteamtags_tool,
1176 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:221177 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:301178 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
1179 'OWNERS']
1180 try:
1181 if files:
1182 input_api.subprocess.check_output(args + files)
1183 return []
1184 except input_api.subprocess.CalledProcessError as error:
1185 return [output_api.PresubmitError(
1186 'checkteamtags.py failed:',
1187 long_text=error.output)]
1188
1189
[email protected]c8278b32012-10-30 20:35:491190def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
1191 """Makes sure we don't include ui/aura/window_property.h
1192 in header files.
1193 """
1194 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1195 errors = []
1196 for f in input_api.AffectedFiles():
1197 if not f.LocalPath().endswith('.h'):
1198 continue
1199 for line_num, line in f.ChangedContents():
1200 if pattern.match(line):
1201 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1202
1203 results = []
1204 if errors:
1205 results.append(output_api.PresubmitError(
1206 'Header files should not include ui/aura/window_property.h', errors))
1207 return results
1208
1209
[email protected]70ca77752012-11-20 03:45:031210def _CheckForVersionControlConflictsInFile(input_api, f):
1211 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1212 errors = []
1213 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231214 if f.LocalPath().endswith('.md'):
1215 # First-level headers in markdown look a lot like version control
1216 # conflict markers. http://daringfireball.net/projects/markdown/basics
1217 continue
[email protected]70ca77752012-11-20 03:45:031218 if pattern.match(line):
1219 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1220 return errors
1221
1222
1223def _CheckForVersionControlConflicts(input_api, output_api):
1224 """Usually this is not intentional and will cause a compile failure."""
1225 errors = []
1226 for f in input_api.AffectedFiles():
1227 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1228
1229 results = []
1230 if errors:
1231 results.append(output_api.PresubmitError(
1232 'Version control conflict markers found, please resolve.', errors))
1233 return results
1234
estadee17314a02017-01-12 16:22:161235def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1236 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1237 errors = []
1238 for f in input_api.AffectedFiles():
1239 for line_num, line in f.ChangedContents():
1240 if pattern.search(line):
1241 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1242
1243 results = []
1244 if errors:
1245 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:501246 'Found Google support URL addressed by answer number. Please replace '
1247 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:161248 return results
1249
[email protected]70ca77752012-11-20 03:45:031250
[email protected]06e6d0ff2012-12-11 01:36:441251def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1252 def FilterFile(affected_file):
1253 """Filter function for use with input_api.AffectedSourceFiles,
1254 below. This filters out everything except non-test files from
1255 top-level directories that generally speaking should not hard-code
1256 service URLs (e.g. src/android_webview/, src/content/ and others).
1257 """
1258 return input_api.FilterSourceFile(
1259 affected_file,
[email protected]78bb39d62012-12-11 15:11:561260 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441261 black_list=(_EXCLUDED_PATHS +
1262 _TEST_CODE_EXCLUDED_PATHS +
1263 input_api.DEFAULT_BLACK_LIST))
1264
reillyi38965732015-11-16 18:27:331265 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1266 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461267 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1268 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441269 problems = [] # items are (filename, line_number, line)
1270 for f in input_api.AffectedSourceFiles(FilterFile):
1271 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461272 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441273 problems.append((f.LocalPath(), line_num, line))
1274
1275 if problems:
[email protected]f7051d52013-04-02 18:31:421276 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441277 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581278 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441279 [' %s:%d: %s' % (
1280 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031281 else:
1282 return []
[email protected]06e6d0ff2012-12-11 01:36:441283
1284
[email protected]d2530012013-01-25 16:39:271285def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1286 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311287 The native_client_sdk directory is excluded because it has auto-generated PNG
1288 files for documentation.
[email protected]d2530012013-01-25 16:39:271289 """
[email protected]d2530012013-01-25 16:39:271290 errors = []
binji0dcdf342014-12-12 18:32:311291 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1292 black_list = (r'^native_client_sdk[\\\/]',)
1293 file_filter = lambda f: input_api.FilterSourceFile(
1294 f, white_list=white_list, black_list=black_list)
1295 for f in input_api.AffectedFiles(include_deletes=False,
1296 file_filter=file_filter):
1297 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271298
1299 results = []
1300 if errors:
1301 results.append(output_api.PresubmitError(
1302 'The name of PNG files should not have abbreviations. \n'
1303 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1304 'Contact [email protected] if you have questions.', errors))
1305 return results
1306
1307
Daniel Cheng4dcdb6b2017-04-13 08:30:171308def _ExtractAddRulesFromParsedDeps(parsed_deps):
1309 """Extract the rules that add dependencies from a parsed DEPS file.
1310
1311 Args:
1312 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1313 add_rules = set()
1314 add_rules.update([
1315 rule[1:] for rule in parsed_deps.get('include_rules', [])
1316 if rule.startswith('+') or rule.startswith('!')
1317 ])
Vaclav Brozekd5de76a2018-03-17 07:57:501318 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:171319 {}).iteritems():
1320 add_rules.update([
1321 rule[1:] for rule in rules
1322 if rule.startswith('+') or rule.startswith('!')
1323 ])
1324 return add_rules
1325
1326
1327def _ParseDeps(contents):
1328 """Simple helper for parsing DEPS files."""
1329 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171330 class _VarImpl:
1331
1332 def __init__(self, local_scope):
1333 self._local_scope = local_scope
1334
1335 def Lookup(self, var_name):
1336 """Implements the Var syntax."""
1337 try:
1338 return self._local_scope['vars'][var_name]
1339 except KeyError:
1340 raise Exception('Var is not defined: %s' % var_name)
1341
1342 local_scope = {}
1343 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171344 'Var': _VarImpl(local_scope).Lookup,
1345 }
1346 exec contents in global_scope, local_scope
1347 return local_scope
1348
1349
1350def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081351 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411352 a set of DEPS entries that we should look up.
1353
1354 For a directory (rather than a specific filename) we fake a path to
1355 a specific filename by adding /DEPS. This is chosen as a file that
1356 will seldom or never be subject to per-file include_rules.
1357 """
[email protected]2b438d62013-11-14 17:54:141358 # We ignore deps entries on auto-generated directories.
1359 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081360
Daniel Cheng4dcdb6b2017-04-13 08:30:171361 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1362 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1363
1364 added_deps = new_deps.difference(old_deps)
1365
[email protected]2b438d62013-11-14 17:54:141366 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171367 for added_dep in added_deps:
1368 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1369 continue
1370 # Assume that a rule that ends in .h is a rule for a specific file.
1371 if added_dep.endswith('.h'):
1372 results.add(added_dep)
1373 else:
1374 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081375 return results
1376
1377
[email protected]e871964c2013-05-13 14:14:551378def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1379 """When a dependency prefixed with + is added to a DEPS file, we
1380 want to make sure that the change is reviewed by an OWNER of the
1381 target file or directory, to avoid layering violations from being
1382 introduced. This check verifies that this happens.
1383 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171384 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241385
1386 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191387 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241388 for f in input_api.AffectedFiles(include_deletes=False,
1389 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551390 filename = input_api.os_path.basename(f.LocalPath())
1391 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171392 virtual_depended_on_files.update(_CalculateAddedDeps(
1393 input_api.os_path,
1394 '\n'.join(f.OldContents()),
1395 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551396
[email protected]e871964c2013-05-13 14:14:551397 if not virtual_depended_on_files:
1398 return []
1399
1400 if input_api.is_committing:
1401 if input_api.tbr:
1402 return [output_api.PresubmitNotifyResult(
1403 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271404 if input_api.dry_run:
1405 return [output_api.PresubmitNotifyResult(
1406 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551407 if not input_api.change.issue:
1408 return [output_api.PresubmitError(
1409 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401410 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551411 output = output_api.PresubmitError
1412 else:
1413 output = output_api.PresubmitNotifyResult
1414
1415 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501416 owner_email, reviewers = (
1417 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1418 input_api,
1419 owners_db.email_regexp,
1420 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551421
1422 owner_email = owner_email or input_api.change.author_email
1423
[email protected]de4f7d22013-05-23 14:27:461424 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511425 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461426 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551427 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1428 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411429
1430 # We strip the /DEPS part that was added by
1431 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1432 # directory.
1433 def StripDeps(path):
1434 start_deps = path.rfind('/DEPS')
1435 if start_deps != -1:
1436 return path[:start_deps]
1437 else:
1438 return path
1439 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551440 for path in missing_files]
1441
1442 if unapproved_dependencies:
1443 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151444 output('You need LGTM from owners of depends-on paths in DEPS that were '
1445 'modified in this CL:\n %s' %
1446 '\n '.join(sorted(unapproved_dependencies)))]
1447 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1448 output_list.append(output(
1449 'Suggested missing target path OWNERS:\n %s' %
1450 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551451 return output_list
1452
1453 return []
1454
1455
[email protected]85218562013-11-22 07:41:401456def _CheckSpamLogging(input_api, output_api):
1457 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1458 black_list = (_EXCLUDED_PATHS +
1459 _TEST_CODE_EXCLUDED_PATHS +
1460 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501461 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191462 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481463 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461464 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121465 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1466 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581467 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161468 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031469 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151470 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1471 r"^chromecast[\\\/]",
1472 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481473 r"^components[\\\/]browser_watcher[\\\/]"
1474 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311475 r"^components[\\\/]html_viewer[\\\/]"
1476 r"web_test_delegate_impl\.cc$",
Samuel Huang577ef6c2018-03-13 18:19:341477 r"^components[\\\/]zucchini[\\\/].*",
peter80739bb2015-10-20 11:17:461478 # TODO(peter): Remove this exception. https://crbug.com/534537
1479 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1480 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251481 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1482 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241483 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111484 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151485 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111486 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521487 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501488 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361489 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311490 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131491 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001492 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441493 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451494 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021495 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351496 r"dump_file_system.cc$",
1497 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401498 source_file_filter = lambda x: input_api.FilterSourceFile(
1499 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1500
thomasanderson625d3932017-03-29 07:16:581501 log_info = set([])
1502 printf = set([])
[email protected]85218562013-11-22 07:41:401503
1504 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581505 for _, line in f.ChangedContents():
1506 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1507 log_info.add(f.LocalPath())
1508 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1509 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371510
thomasanderson625d3932017-03-29 07:16:581511 if input_api.re.search(r"\bprintf\(", line):
1512 printf.add(f.LocalPath())
1513 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1514 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401515
1516 if log_info:
1517 return [output_api.PresubmitError(
1518 'These files spam the console log with LOG(INFO):',
1519 items=log_info)]
1520 if printf:
1521 return [output_api.PresubmitError(
1522 'These files spam the console log with printf/fprintf:',
1523 items=printf)]
1524 return []
1525
1526
[email protected]49aa76a2013-12-04 06:59:161527def _CheckForAnonymousVariables(input_api, output_api):
1528 """These types are all expected to hold locks while in scope and
1529 so should never be anonymous (which causes them to be immediately
1530 destroyed)."""
1531 they_who_must_be_named = [
1532 'base::AutoLock',
1533 'base::AutoReset',
1534 'base::AutoUnlock',
1535 'SkAutoAlphaRestore',
1536 'SkAutoBitmapShaderInstall',
1537 'SkAutoBlitterChoose',
1538 'SkAutoBounderCommit',
1539 'SkAutoCallProc',
1540 'SkAutoCanvasRestore',
1541 'SkAutoCommentBlock',
1542 'SkAutoDescriptor',
1543 'SkAutoDisableDirectionCheck',
1544 'SkAutoDisableOvalCheck',
1545 'SkAutoFree',
1546 'SkAutoGlyphCache',
1547 'SkAutoHDC',
1548 'SkAutoLockColors',
1549 'SkAutoLockPixels',
1550 'SkAutoMalloc',
1551 'SkAutoMaskFreeImage',
1552 'SkAutoMutexAcquire',
1553 'SkAutoPathBoundsUpdate',
1554 'SkAutoPDFRelease',
1555 'SkAutoRasterClipValidate',
1556 'SkAutoRef',
1557 'SkAutoTime',
1558 'SkAutoTrace',
1559 'SkAutoUnref',
1560 ]
1561 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1562 # bad: base::AutoLock(lock.get());
1563 # not bad: base::AutoLock lock(lock.get());
1564 bad_pattern = input_api.re.compile(anonymous)
1565 # good: new base::AutoLock(lock.get())
1566 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1567 errors = []
1568
1569 for f in input_api.AffectedFiles():
1570 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1571 continue
1572 for linenum, line in f.ChangedContents():
1573 if bad_pattern.search(line) and not good_pattern.search(line):
1574 errors.append('%s:%d' % (f.LocalPath(), linenum))
1575
1576 if errors:
1577 return [output_api.PresubmitError(
1578 'These lines create anonymous variables that need to be named:',
1579 items=errors)]
1580 return []
1581
1582
Peter Kasting4844e46e2018-02-23 07:27:101583def _CheckUniquePtr(input_api, output_api):
1584 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1585 sources = lambda affected_file: input_api.FilterSourceFile(
1586 affected_file,
1587 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1588 input_api.DEFAULT_BLACK_LIST),
1589 white_list=(file_inclusion_pattern,))
Vaclav Brozeka54c528b2018-04-06 19:23:551590
1591 # Pattern to capture a single "<...>" block of template arguments. It can
1592 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
1593 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
1594 # latter would likely require counting that < and > match, which is not
1595 # expressible in regular languages. Should the need arise, one can introduce
1596 # limited counting (matching up to a total number of nesting depth), which
1597 # should cover all practical cases for already a low nesting limit.
1598 template_arg_pattern = (
1599 r'<[^>]*' # Opening block of <.
1600 r'>([^<]*>)?') # Closing block of >.
1601 # Prefix expressing that whatever follows is not already inside a <...>
1602 # block.
1603 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:101604 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:551605 not_inside_template_arg_pattern
1606 + r'\bstd::unique_ptr'
1607 + template_arg_pattern
1608 + r'\(\)')
1609
1610 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
1611 template_arg_no_array_pattern = (
1612 r'<[^>]*[^]]' # Opening block of <.
1613 r'>([^(<]*[^]]>)?') # Closing block of >.
1614 # Prefix saying that what follows is the start of an expression.
1615 start_of_expr_pattern = r'(=|\breturn|^)\s*'
1616 # Suffix saying that what follows are call parentheses with a non-empty list
1617 # of arguments.
1618 nonempty_arg_list_pattern = r'\(([^)]|$)'
1619 return_construct_pattern = input_api.re.compile(
1620 start_of_expr_pattern
1621 + r'std::unique_ptr'
1622 + template_arg_no_array_pattern
1623 + nonempty_arg_list_pattern)
1624
Vaclav Brozek851d9602018-04-04 16:13:051625 problems_constructor = []
1626 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:101627 for f in input_api.AffectedSourceFiles(sources):
1628 for line_number, line in f.ChangedContents():
1629 # Disallow:
1630 # return std::unique_ptr<T>(foo);
1631 # bar = std::unique_ptr<T>(foo);
1632 # But allow:
1633 # return std::unique_ptr<T[]>(foo);
1634 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozek851d9602018-04-04 16:13:051635 local_path = f.LocalPath()
Peter Kasting4844e46e2018-02-23 07:27:101636 if return_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:051637 problems_constructor.append(
1638 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:101639 # Disallow:
1640 # std::unique_ptr<T>()
1641 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:051642 problems_nullptr.append(
1643 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1644
1645 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:161646 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:051647 errors.append(output_api.PresubmitError(
1648 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:161649 problems_nullptr))
1650 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:051651 errors.append(output_api.PresubmitError(
1652 'The following files use explicit std::unique_ptr constructor.'
1653 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:161654 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:101655 return errors
1656
1657
[email protected]999261d2014-03-03 20:08:081658def _CheckUserActionUpdate(input_api, output_api):
1659 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521660 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081661 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521662 # If actions.xml is already included in the changelist, the PRESUBMIT
1663 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081664 return []
1665
[email protected]999261d2014-03-03 20:08:081666 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1667 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521668 current_actions = None
[email protected]999261d2014-03-03 20:08:081669 for f in input_api.AffectedFiles(file_filter=file_filter):
1670 for line_num, line in f.ChangedContents():
1671 match = input_api.re.search(action_re, line)
1672 if match:
[email protected]2f92dec2014-03-07 19:21:521673 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1674 # loaded only once.
1675 if not current_actions:
1676 with open('tools/metrics/actions/actions.xml') as actions_f:
1677 current_actions = actions_f.read()
1678 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081679 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521680 action = 'name="{0}"'.format(action_name)
1681 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081682 return [output_api.PresubmitPromptWarning(
1683 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521684 'tools/metrics/actions/actions.xml. Please run '
1685 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081686 % (f.LocalPath(), line_num, action_name))]
1687 return []
1688
1689
Daniel Cheng13ca61a882017-08-25 15:11:251690def _ImportJSONCommentEater(input_api):
1691 import sys
1692 sys.path = sys.path + [input_api.os_path.join(
1693 input_api.PresubmitLocalPath(),
1694 'tools', 'json_comment_eater')]
1695 import json_comment_eater
1696 return json_comment_eater
1697
1698
[email protected]99171a92014-06-03 08:44:471699def _GetJSONParseError(input_api, filename, eat_comments=True):
1700 try:
1701 contents = input_api.ReadFile(filename)
1702 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251703 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131704 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471705
1706 input_api.json.loads(contents)
1707 except ValueError as e:
1708 return e
1709 return None
1710
1711
1712def _GetIDLParseError(input_api, filename):
1713 try:
1714 contents = input_api.ReadFile(filename)
1715 idl_schema = input_api.os_path.join(
1716 input_api.PresubmitLocalPath(),
1717 'tools', 'json_schema_compiler', 'idl_schema.py')
1718 process = input_api.subprocess.Popen(
1719 [input_api.python_executable, idl_schema],
1720 stdin=input_api.subprocess.PIPE,
1721 stdout=input_api.subprocess.PIPE,
1722 stderr=input_api.subprocess.PIPE,
1723 universal_newlines=True)
1724 (_, error) = process.communicate(input=contents)
1725 return error or None
1726 except ValueError as e:
1727 return e
1728
1729
1730def _CheckParseErrors(input_api, output_api):
1731 """Check that IDL and JSON files do not contain syntax errors."""
1732 actions = {
1733 '.idl': _GetIDLParseError,
1734 '.json': _GetJSONParseError,
1735 }
[email protected]99171a92014-06-03 08:44:471736 # Most JSON files are preprocessed and support comments, but these do not.
1737 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491738 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471739 ]
1740 # Only run IDL checker on files in these directories.
1741 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491742 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1743 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471744 ]
1745
1746 def get_action(affected_file):
1747 filename = affected_file.LocalPath()
1748 return actions.get(input_api.os_path.splitext(filename)[1])
1749
[email protected]99171a92014-06-03 08:44:471750 def FilterFile(affected_file):
1751 action = get_action(affected_file)
1752 if not action:
1753 return False
1754 path = affected_file.LocalPath()
1755
Sean Kau46e29bc2017-08-28 16:31:161756 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471757 return False
1758
1759 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161760 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471761 return False
1762 return True
1763
1764 results = []
1765 for affected_file in input_api.AffectedFiles(
1766 file_filter=FilterFile, include_deletes=False):
1767 action = get_action(affected_file)
1768 kwargs = {}
1769 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161770 _MatchesFile(input_api, json_no_comments_patterns,
1771 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471772 kwargs['eat_comments'] = False
1773 parse_error = action(input_api,
1774 affected_file.AbsoluteLocalPath(),
1775 **kwargs)
1776 if parse_error:
1777 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1778 (affected_file.LocalPath(), parse_error)))
1779 return results
1780
1781
[email protected]760deea2013-12-10 19:33:491782def _CheckJavaStyle(input_api, output_api):
1783 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471784 import sys
[email protected]760deea2013-12-10 19:33:491785 original_sys_path = sys.path
1786 try:
1787 sys.path = sys.path + [input_api.os_path.join(
1788 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1789 import checkstyle
1790 finally:
1791 # Restore sys.path to what it was before.
1792 sys.path = original_sys_path
1793
1794 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091795 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511796 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491797
1798
Sean Kau46e29bc2017-08-28 16:31:161799def _MatchesFile(input_api, patterns, path):
1800 for pattern in patterns:
1801 if input_api.re.search(pattern, path):
1802 return True
1803 return False
1804
1805
Daniel Cheng7052cdf2017-11-21 19:23:291806def _GetOwnersFilesToCheckForIpcOwners(input_api):
1807 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:171808
Daniel Cheng7052cdf2017-11-21 19:23:291809 Returns:
1810 A dictionary mapping an OWNER file to the list of OWNERS rules it must
1811 contain to cover IPC-related files with noparent reviewer rules.
1812 """
1813 # Whether or not a file affects IPC is (mostly) determined by a simple list
1814 # of filename patterns.
dchenge07de812016-06-20 19:27:171815 file_patterns = [
palmerb19a0932017-01-24 04:00:311816 # Legacy IPC:
dchenge07de812016-06-20 19:27:171817 '*_messages.cc',
1818 '*_messages*.h',
1819 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311820 # Mojo IPC:
dchenge07de812016-06-20 19:27:171821 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:471822 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:171823 '*_struct_traits*.*',
1824 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311825 '*.typemap',
1826 # Android native IPC:
1827 '*.aidl',
1828 # Blink uses a different file naming convention:
1829 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:471830 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:171831 '*StructTraits*.*',
1832 '*TypeConverter*.*',
1833 ]
1834
scottmg7a6ed5ba2016-11-04 18:22:041835 # These third_party directories do not contain IPCs, but contain files
1836 # matching the above patterns, which trigger false positives.
1837 exclude_paths = [
1838 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291839 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041840 ]
1841
dchenge07de812016-06-20 19:27:171842 # Dictionary mapping an OWNERS file path to Patterns.
1843 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1844 # rules ) to a PatternEntry.
1845 # PatternEntry is a dictionary with two keys:
1846 # - 'files': the files that are matched by this pattern
1847 # - 'rules': the per-file rules needed for this pattern
1848 # For example, if we expect OWNERS file to contain rules for *.mojom and
1849 # *_struct_traits*.*, Patterns might look like this:
1850 # {
1851 # '*.mojom': {
1852 # 'files': ...,
1853 # 'rules': [
1854 # 'per-file *.mojom=set noparent',
1855 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1856 # ],
1857 # },
1858 # '*_struct_traits*.*': {
1859 # 'files': ...,
1860 # 'rules': [
1861 # 'per-file *_struct_traits*.*=set noparent',
1862 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1863 # ],
1864 # },
1865 # }
1866 to_check = {}
1867
Daniel Cheng13ca61a882017-08-25 15:11:251868 def AddPatternToCheck(input_file, pattern):
1869 owners_file = input_api.os_path.join(
1870 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1871 if owners_file not in to_check:
1872 to_check[owners_file] = {}
1873 if pattern not in to_check[owners_file]:
1874 to_check[owners_file][pattern] = {
1875 'files': [],
1876 'rules': [
1877 'per-file %s=set noparent' % pattern,
1878 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1879 ]
1880 }
Vaclav Brozekd5de76a2018-03-17 07:57:501881 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:251882
dchenge07de812016-06-20 19:27:171883 # Iterate through the affected files to see what we actually need to check
1884 # for. We should only nag patch authors about per-file rules if a file in that
1885 # directory would match that pattern. If a directory only contains *.mojom
1886 # files and no *_messages*.h files, we should only nag about rules for
1887 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251888 for f in input_api.AffectedFiles(include_deletes=False):
1889 # Manifest files don't have a strong naming convention. Instead, scan
1890 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161891 if (f.LocalPath().endswith('.json') and
1892 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1893 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251894 json_comment_eater = _ImportJSONCommentEater(input_api)
1895 mostly_json_lines = '\n'.join(f.NewContents())
1896 # Comments aren't allowed in strict JSON, so filter them out.
1897 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:431898 try:
1899 json_content = input_api.json.loads(json_lines)
1900 except:
1901 # There's another PRESUBMIT check that already verifies that JSON files
1902 # are not invalid, so no need to emit another warning here.
1903 continue
Daniel Cheng13ca61a882017-08-25 15:11:251904 if 'interface_provider_specs' in json_content:
1905 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171906 for pattern in file_patterns:
1907 if input_api.fnmatch.fnmatch(
1908 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041909 skip = False
1910 for exclude in exclude_paths:
1911 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1912 skip = True
1913 break
1914 if skip:
1915 continue
Daniel Cheng13ca61a882017-08-25 15:11:251916 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171917 break
1918
Daniel Cheng7052cdf2017-11-21 19:23:291919 return to_check
1920
1921
1922def _CheckIpcOwners(input_api, output_api):
1923 """Checks that affected files involving IPC have an IPC OWNERS rule."""
1924 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
1925
1926 if to_check:
1927 # If there are any OWNERS files to check, there are IPC-related changes in
1928 # this CL. Auto-CC the review list.
1929 output_api.AppendCC('[email protected]')
1930
1931 # Go through the OWNERS files to check, filtering out rules that are already
1932 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:171933 for owners_file, patterns in to_check.iteritems():
1934 try:
1935 with file(owners_file) as f:
1936 lines = set(f.read().splitlines())
1937 for entry in patterns.itervalues():
1938 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1939 ]
1940 except IOError:
1941 # No OWNERS file, so all the rules are definitely missing.
1942 continue
1943
1944 # All the remaining lines weren't found in OWNERS files, so emit an error.
1945 errors = []
1946 for owners_file, patterns in to_check.iteritems():
1947 missing_lines = []
1948 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:501949 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:171950 missing_lines.extend(entry['rules'])
1951 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1952 if missing_lines:
1953 errors.append(
Daniel Cheng52111692017-06-14 08:00:591954 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171955 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1956
1957 results = []
1958 if errors:
vabrf5ce3bf92016-07-11 14:52:411959 if input_api.is_committing:
1960 output = output_api.PresubmitError
1961 else:
1962 output = output_api.PresubmitPromptWarning
1963 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591964 'Found OWNERS files that need to be updated for IPC security ' +
1965 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171966 long_text='\n\n'.join(errors)))
1967
1968 return results
1969
1970
jbriance9e12f162016-11-25 07:57:501971def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311972 """Checks that added or removed lines in non third party affected
1973 header files do not lead to new useless class or struct forward
1974 declaration.
jbriance9e12f162016-11-25 07:57:501975 """
1976 results = []
1977 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1978 input_api.re.MULTILINE)
1979 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1980 input_api.re.MULTILINE)
1981 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311982 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191983 not f.LocalPath().startswith('third_party/blink') and
1984 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311985 not f.LocalPath().startswith('third_party/WebKit') and
1986 not f.LocalPath().startswith('third_party\\WebKit')):
1987 continue
1988
jbriance9e12f162016-11-25 07:57:501989 if not f.LocalPath().endswith('.h'):
1990 continue
1991
1992 contents = input_api.ReadFile(f)
1993 fwd_decls = input_api.re.findall(class_pattern, contents)
1994 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1995
1996 useless_fwd_decls = []
1997 for decl in fwd_decls:
1998 count = sum(1 for _ in input_api.re.finditer(
1999 r'\b%s\b' % input_api.re.escape(decl), contents))
2000 if count == 1:
2001 useless_fwd_decls.append(decl)
2002
2003 if not useless_fwd_decls:
2004 continue
2005
2006 for line in f.GenerateScmDiff().splitlines():
2007 if (line.startswith('-') and not line.startswith('--') or
2008 line.startswith('+') and not line.startswith('++')):
2009 for decl in useless_fwd_decls:
2010 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
2011 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:242012 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:502013 (f.LocalPath(), decl)))
2014 useless_fwd_decls.remove(decl)
2015
2016 return results
2017
2018
dskiba88634f4e2015-08-14 23:03:292019def _CheckAndroidToastUsage(input_api, output_api):
2020 """Checks that code uses org.chromium.ui.widget.Toast instead of
2021 android.widget.Toast (Chromium Toast doesn't force hardware
2022 acceleration on low-end devices, saving memory).
2023 """
2024 toast_import_pattern = input_api.re.compile(
2025 r'^import android\.widget\.Toast;$')
2026
2027 errors = []
2028
2029 sources = lambda affected_file: input_api.FilterSourceFile(
2030 affected_file,
2031 black_list=(_EXCLUDED_PATHS +
2032 _TEST_CODE_EXCLUDED_PATHS +
2033 input_api.DEFAULT_BLACK_LIST +
2034 (r'^chromecast[\\\/].*',
2035 r'^remoting[\\\/].*')),
2036 white_list=(r'.*\.java$',))
2037
2038 for f in input_api.AffectedSourceFiles(sources):
2039 for line_num, line in f.ChangedContents():
2040 if toast_import_pattern.search(line):
2041 errors.append("%s:%d" % (f.LocalPath(), line_num))
2042
2043 results = []
2044
2045 if errors:
2046 results.append(output_api.PresubmitError(
2047 'android.widget.Toast usage is detected. Android toasts use hardware'
2048 ' acceleration, and can be\ncostly on low-end devices. Please use'
2049 ' org.chromium.ui.widget.Toast instead.\n'
2050 'Contact [email protected] if you have any questions.',
2051 errors))
2052
2053 return results
2054
2055
dgnaa68d5e2015-06-10 10:08:222056def _CheckAndroidCrLogUsage(input_api, output_api):
2057 """Checks that new logs using org.chromium.base.Log:
2058 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:512059 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:222060 """
pkotwicza1dd0b002016-05-16 14:41:042061
torne89540622017-03-24 19:41:302062 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:042063 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:302064 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:042065 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:302066 # WebView license viewer code cannot depend on //base; used in stub APK.
2067 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
2068 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:042069 ]
2070
dgnaa68d5e2015-06-10 10:08:222071 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:122072 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
2073 class_in_base_pattern = input_api.re.compile(
2074 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
2075 has_some_log_import_pattern = input_api.re.compile(
2076 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222077 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:122078 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:222079 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:512080 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:222081 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222082
Vincent Scheib16d7b272015-09-15 18:09:072083 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:222084 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:042085 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
2086 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:122087
dgnaa68d5e2015-06-10 10:08:222088 tag_decl_errors = []
2089 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:122090 tag_errors = []
dgn38736db2015-09-18 19:20:512091 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:122092 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:222093
2094 for f in input_api.AffectedSourceFiles(sources):
2095 file_content = input_api.ReadFile(f)
2096 has_modified_logs = False
2097
2098 # Per line checks
dgn87d9fb62015-06-12 09:15:122099 if (cr_log_import_pattern.search(file_content) or
2100 (class_in_base_pattern.search(file_content) and
2101 not has_some_log_import_pattern.search(file_content))):
2102 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:222103 for line_num, line in f.ChangedContents():
2104
2105 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:122106 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:222107 if match:
2108 has_modified_logs = True
2109
2110 # Make sure it uses "TAG"
2111 if not match.group('tag') == 'TAG':
2112 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:122113 else:
2114 # Report non cr Log function calls in changed lines
2115 for line_num, line in f.ChangedContents():
2116 if log_call_pattern.search(line):
2117 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:222118
2119 # Per file checks
2120 if has_modified_logs:
2121 # Make sure the tag is using the "cr" prefix and is not too long
2122 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:512123 tag_name = match.group('name') if match else None
2124 if not tag_name:
dgnaa68d5e2015-06-10 10:08:222125 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512126 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:222127 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512128 elif '.' in tag_name:
2129 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:222130
2131 results = []
2132 if tag_decl_errors:
2133 results.append(output_api.PresubmitPromptWarning(
2134 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:512135 '"private static final String TAG = "<package tag>".\n'
2136 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222137 tag_decl_errors))
2138
2139 if tag_length_errors:
2140 results.append(output_api.PresubmitError(
2141 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:512142 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222143 tag_length_errors))
2144
2145 if tag_errors:
2146 results.append(output_api.PresubmitPromptWarning(
2147 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
2148 tag_errors))
2149
dgn87d9fb62015-06-12 09:15:122150 if util_log_errors:
dgn4401aa52015-04-29 16:26:172151 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:122152 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
2153 util_log_errors))
2154
dgn38736db2015-09-18 19:20:512155 if tag_with_dot_errors:
2156 results.append(output_api.PresubmitPromptWarning(
2157 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
2158 tag_with_dot_errors))
2159
dgn4401aa52015-04-29 16:26:172160 return results
2161
2162
Yoland Yanb92fa522017-08-28 17:37:062163def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
2164 """Checks that junit.framework.* is no longer used."""
2165 deprecated_junit_framework_pattern = input_api.re.compile(
2166 r'^import junit\.framework\..*;',
2167 input_api.re.MULTILINE)
2168 sources = lambda x: input_api.FilterSourceFile(
2169 x, white_list=(r'.*\.java$',), black_list=None)
2170 errors = []
2171 for f in input_api.AffectedFiles(sources):
2172 for line_num, line in f.ChangedContents():
2173 if deprecated_junit_framework_pattern.search(line):
2174 errors.append("%s:%d" % (f.LocalPath(), line_num))
2175
2176 results = []
2177 if errors:
2178 results.append(output_api.PresubmitError(
2179 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
2180 '(org.junit.*) from //third_party/junit. Contact [email protected]'
2181 ' if you have any question.', errors))
2182 return results
2183
2184
2185def _CheckAndroidTestJUnitInheritance(input_api, output_api):
2186 """Checks that if new Java test classes have inheritance.
2187 Either the new test class is JUnit3 test or it is a JUnit4 test class
2188 with a base class, either case is undesirable.
2189 """
2190 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
2191
2192 sources = lambda x: input_api.FilterSourceFile(
2193 x, white_list=(r'.*Test\.java$',), black_list=None)
2194 errors = []
2195 for f in input_api.AffectedFiles(sources):
2196 if not f.OldContents():
2197 class_declaration_start_flag = False
2198 for line_num, line in f.ChangedContents():
2199 if class_declaration_pattern.search(line):
2200 class_declaration_start_flag = True
2201 if class_declaration_start_flag and ' extends ' in line:
2202 errors.append('%s:%d' % (f.LocalPath(), line_num))
2203 if '{' in line:
2204 class_declaration_start_flag = False
2205
2206 results = []
2207 if errors:
2208 results.append(output_api.PresubmitPromptWarning(
2209 'The newly created files include Test classes that inherits from base'
2210 ' class. Please do not use inheritance in JUnit4 tests or add new'
2211 ' JUnit3 tests. Contact [email protected] if you have any'
2212 ' questions.', errors))
2213 return results
2214
yolandyan45001472016-12-21 21:12:422215def _CheckAndroidTestAnnotationUsage(input_api, output_api):
2216 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
2217 deprecated_annotation_import_pattern = input_api.re.compile(
2218 r'^import android\.test\.suitebuilder\.annotation\..*;',
2219 input_api.re.MULTILINE)
2220 sources = lambda x: input_api.FilterSourceFile(
2221 x, white_list=(r'.*\.java$',), black_list=None)
2222 errors = []
2223 for f in input_api.AffectedFiles(sources):
2224 for line_num, line in f.ChangedContents():
2225 if deprecated_annotation_import_pattern.search(line):
2226 errors.append("%s:%d" % (f.LocalPath(), line_num))
2227
2228 results = []
2229 if errors:
2230 results.append(output_api.PresubmitError(
2231 'Annotations in android.test.suitebuilder.annotation have been'
2232 ' deprecated since API level 24. Please use android.support.test.filters'
2233 ' from //third_party/android_support_test_runner:runner_java instead.'
2234 ' Contact [email protected] if you have any questions.', errors))
2235 return results
2236
2237
agrieve7b6479d82015-10-07 14:24:222238def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
2239 """Checks if MDPI assets are placed in a correct directory."""
2240 file_filter = lambda f: (f.LocalPath().endswith('.png') and
2241 ('/res/drawable/' in f.LocalPath() or
2242 '/res/drawable-ldrtl/' in f.LocalPath()))
2243 errors = []
2244 for f in input_api.AffectedFiles(include_deletes=False,
2245 file_filter=file_filter):
2246 errors.append(' %s' % f.LocalPath())
2247
2248 results = []
2249 if errors:
2250 results.append(output_api.PresubmitError(
2251 'MDPI assets should be placed in /res/drawable-mdpi/ or '
2252 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
2253 '/res/drawable-ldrtl/.\n'
2254 'Contact [email protected] if you have questions.', errors))
2255 return results
2256
2257
Nate Fischer535972b2017-09-16 01:06:182258def _CheckAndroidWebkitImports(input_api, output_api):
2259 """Checks that code uses org.chromium.base.Callback instead of
2260 android.widget.ValueCallback except in the WebView glue layer.
2261 """
2262 valuecallback_import_pattern = input_api.re.compile(
2263 r'^import android\.webkit\.ValueCallback;$')
2264
2265 errors = []
2266
2267 sources = lambda affected_file: input_api.FilterSourceFile(
2268 affected_file,
2269 black_list=(_EXCLUDED_PATHS +
2270 _TEST_CODE_EXCLUDED_PATHS +
2271 input_api.DEFAULT_BLACK_LIST +
2272 (r'^android_webview[\\\/]glue[\\\/].*',)),
2273 white_list=(r'.*\.java$',))
2274
2275 for f in input_api.AffectedSourceFiles(sources):
2276 for line_num, line in f.ChangedContents():
2277 if valuecallback_import_pattern.search(line):
2278 errors.append("%s:%d" % (f.LocalPath(), line_num))
2279
2280 results = []
2281
2282 if errors:
2283 results.append(output_api.PresubmitError(
2284 'android.webkit.ValueCallback usage is detected outside of the glue'
2285 ' layer. To stay compatible with the support library, android.webkit.*'
2286 ' classes should only be used inside the glue layer and'
2287 ' org.chromium.base.Callback should be used instead.',
2288 errors))
2289
2290 return results
2291
2292
agrievef32bcc72016-04-04 14:57:402293class PydepsChecker(object):
2294 def __init__(self, input_api, pydeps_files):
2295 self._file_cache = {}
2296 self._input_api = input_api
2297 self._pydeps_files = pydeps_files
2298
2299 def _LoadFile(self, path):
2300 """Returns the list of paths within a .pydeps file relative to //."""
2301 if path not in self._file_cache:
2302 with open(path) as f:
2303 self._file_cache[path] = f.read()
2304 return self._file_cache[path]
2305
2306 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
2307 """Returns an interable of paths within the .pydep, relativized to //."""
2308 os_path = self._input_api.os_path
2309 pydeps_dir = os_path.dirname(pydeps_path)
2310 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2311 if not l.startswith('*'))
2312 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2313
2314 def _CreateFilesToPydepsMap(self):
2315 """Returns a map of local_path -> list_of_pydeps."""
2316 ret = {}
2317 for pydep_local_path in self._pydeps_files:
2318 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2319 ret.setdefault(path, []).append(pydep_local_path)
2320 return ret
2321
2322 def ComputeAffectedPydeps(self):
2323 """Returns an iterable of .pydeps files that might need regenerating."""
2324 affected_pydeps = set()
2325 file_to_pydeps_map = None
2326 for f in self._input_api.AffectedFiles(include_deletes=True):
2327 local_path = f.LocalPath()
2328 if local_path == 'DEPS':
2329 return self._pydeps_files
2330 elif local_path.endswith('.pydeps'):
2331 if local_path in self._pydeps_files:
2332 affected_pydeps.add(local_path)
2333 elif local_path.endswith('.py'):
2334 if file_to_pydeps_map is None:
2335 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2336 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2337 return affected_pydeps
2338
2339 def DetermineIfStale(self, pydeps_path):
2340 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412341 import difflib
John Budorick47ca3fe2018-02-10 00:53:102342 import os
2343
agrievef32bcc72016-04-04 14:57:402344 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2345 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:102346 env = dict(os.environ)
2347 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:402348 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:102349 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412350 old_contents = old_pydeps_data[2:]
2351 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402352 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412353 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402354
2355
2356def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2357 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:402358 # This check is for Python dependency lists (.pydeps files), and involves
2359 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
2360 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:282361 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002362 return []
Mostyn Bramley-Moore6b427322017-12-21 22:11:022363 # TODO(agrieve): Update when there's a better way to detect
2364 # this: crbug.com/570091
agrievef32bcc72016-04-04 14:57:402365 is_android = input_api.os_path.exists('third_party/android_tools')
2366 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2367 results = []
2368 # First, check for new / deleted .pydeps.
2369 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:032370 # Check whether we are running the presubmit check for a file in src.
2371 # f.LocalPath is relative to repo (src, or internal repo).
2372 # os_path.exists is relative to src repo.
2373 # Therefore if os_path.exists is true, it means f.LocalPath is relative
2374 # to src and we can conclude that the pydeps is in src.
2375 if input_api.os_path.exists(f.LocalPath()):
2376 if f.LocalPath().endswith('.pydeps'):
2377 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2378 results.append(output_api.PresubmitError(
2379 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2380 'remove %s' % f.LocalPath()))
2381 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2382 results.append(output_api.PresubmitError(
2383 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2384 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:402385
2386 if results:
2387 return results
2388
2389 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2390
2391 for pydep_path in checker.ComputeAffectedPydeps():
2392 try:
phajdan.jr0d9878552016-11-04 10:49:412393 result = checker.DetermineIfStale(pydep_path)
2394 if result:
2395 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402396 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412397 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2398 'To regenerate, run:\n\n %s' %
2399 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402400 except input_api.subprocess.CalledProcessError as error:
2401 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2402 long_text=error.output)]
2403
2404 return results
2405
2406
glidere61efad2015-02-18 17:39:432407def _CheckSingletonInHeaders(input_api, output_api):
2408 """Checks to make sure no header files have |Singleton<|."""
2409 def FileFilter(affected_file):
2410 # It's ok for base/memory/singleton.h to have |Singleton<|.
2411 black_list = (_EXCLUDED_PATHS +
2412 input_api.DEFAULT_BLACK_LIST +
Michael Warrese4451492018-03-07 04:42:472413 (r"^base[\\\/]memory[\\\/]singleton\.h$",
2414 r"^net[\\\/]quic[\\\/]platform[\\\/]impl[\\\/]"
2415 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:432416 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2417
sergeyu34d21222015-09-16 00:11:442418 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432419 files = []
2420 for f in input_api.AffectedSourceFiles(FileFilter):
2421 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2422 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2423 contents = input_api.ReadFile(f)
2424 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242425 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432426 pattern.search(line)):
2427 files.append(f)
2428 break
2429
2430 if files:
yolandyandaabc6d2016-04-18 18:29:392431 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442432 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432433 'Please move them to an appropriate source file so that the ' +
2434 'template gets instantiated in a single compilation unit.',
2435 files) ]
2436 return []
2437
2438
[email protected]fd20b902014-05-09 02:14:532439_DEPRECATED_CSS = [
2440 # Values
2441 ( "-webkit-box", "flex" ),
2442 ( "-webkit-inline-box", "inline-flex" ),
2443 ( "-webkit-flex", "flex" ),
2444 ( "-webkit-inline-flex", "inline-flex" ),
2445 ( "-webkit-min-content", "min-content" ),
2446 ( "-webkit-max-content", "max-content" ),
2447
2448 # Properties
2449 ( "-webkit-background-clip", "background-clip" ),
2450 ( "-webkit-background-origin", "background-origin" ),
2451 ( "-webkit-background-size", "background-size" ),
2452 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442453 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532454
2455 # Functions
2456 ( "-webkit-gradient", "gradient" ),
2457 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2458 ( "-webkit-linear-gradient", "linear-gradient" ),
2459 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2460 ( "-webkit-radial-gradient", "radial-gradient" ),
2461 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2462]
2463
dbeam1ec68ac2016-12-15 05:22:242464def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532465 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252466 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342467 documentation and iOS CSS for dom distiller
2468 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252469 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532470 results = []
dbeam070cfe62014-10-22 06:44:022471 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252472 black_list = (_EXCLUDED_PATHS +
2473 _TEST_CODE_EXCLUDED_PATHS +
2474 input_api.DEFAULT_BLACK_LIST +
2475 (r"^chrome/common/extensions/docs",
2476 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342477 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442478 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252479 r"^native_client_sdk"))
2480 file_filter = lambda f: input_api.FilterSourceFile(
2481 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532482 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2483 for line_num, line in fpath.ChangedContents():
2484 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022485 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532486 results.append(output_api.PresubmitError(
2487 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2488 (fpath.LocalPath(), line_num, deprecated_value, value)))
2489 return results
2490
mohan.reddyf21db962014-10-16 12:26:472491
dbeam070cfe62014-10-22 06:44:022492_DEPRECATED_JS = [
2493 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2494 ( "__defineGetter__", "Object.defineProperty" ),
2495 ( "__defineSetter__", "Object.defineProperty" ),
2496]
2497
dbeam1ec68ac2016-12-15 05:22:242498def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022499 """Make sure that we don't use deprecated JS in Chrome code."""
2500 results = []
2501 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2502 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2503 input_api.DEFAULT_BLACK_LIST)
2504 file_filter = lambda f: input_api.FilterSourceFile(
2505 f, white_list=file_inclusion_pattern, black_list=black_list)
2506 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2507 for lnum, line in fpath.ChangedContents():
2508 for (deprecated, replacement) in _DEPRECATED_JS:
2509 if deprecated in line:
2510 results.append(output_api.PresubmitError(
2511 "%s:%d: Use of deprecated JS %s, use %s instead" %
2512 (fpath.LocalPath(), lnum, deprecated, replacement)))
2513 return results
2514
dpapadd651231d82017-07-21 02:44:472515def _CheckForRiskyJsArrowFunction(line_number, line):
2516 if ' => ' in line:
2517 return "line %d, is using an => (arrow) function\n %s\n" % (
2518 line_number, line)
2519 return ''
2520
2521def _CheckForRiskyJsConstLet(input_api, line_number, line):
2522 if input_api.re.match('^\s*(const|let)\s', line):
2523 return "line %d, is using const/let keyword\n %s\n" % (
2524 line_number, line)
2525 return ''
dbeam070cfe62014-10-22 06:44:022526
dbeam1ec68ac2016-12-15 05:22:242527def _CheckForRiskyJsFeatures(input_api, output_api):
2528 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002529 # 'ui/webui/resources/cr_components are not allowed on ios'
2530 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572531 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002532 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472533 results = []
dbeam1ec68ac2016-12-15 05:22:242534 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472535 arrow_error_lines = []
2536 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242537 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472538 arrow_error_lines += filter(None, [
2539 _CheckForRiskyJsArrowFunction(lnum, line),
2540 ])
dbeam1ec68ac2016-12-15 05:22:242541
dpapadd651231d82017-07-21 02:44:472542 const_let_error_lines += filter(None, [
2543 _CheckForRiskyJsConstLet(input_api, lnum, line),
2544 ])
dbeam1ec68ac2016-12-15 05:22:242545
dpapadd651231d82017-07-21 02:44:472546 if arrow_error_lines:
2547 arrow_error_lines = map(
2548 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2549 results.append(
2550 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2551"""
2552Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242553%s
2554Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2555https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472556""" % f.LocalPath()
2557 ])))
dbeam1ec68ac2016-12-15 05:22:242558
dpapadd651231d82017-07-21 02:44:472559 if const_let_error_lines:
2560 const_let_error_lines = map(
2561 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2562 results.append(
2563 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2564"""
2565Use of const/let keywords detected in:
2566%s
2567Please ensure your code does not run on iOS9 because const/let is not fully
2568supported.
2569https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2570https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2571""" % f.LocalPath()
2572 ])))
2573
2574 return results
dbeam1ec68ac2016-12-15 05:22:242575
rlanday6802cf632017-05-30 17:48:362576def _CheckForRelativeIncludes(input_api, output_api):
2577 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2578 import sys
2579 original_sys_path = sys.path
2580 try:
2581 sys.path = sys.path + [input_api.os_path.join(
2582 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2583 from cpp_checker import CppChecker
2584 finally:
2585 # Restore sys.path to what it was before.
2586 sys.path = original_sys_path
2587
2588 bad_files = {}
2589 for f in input_api.AffectedFiles(include_deletes=False):
2590 if (f.LocalPath().startswith('third_party') and
2591 not f.LocalPath().startswith('third_party/WebKit') and
2592 not f.LocalPath().startswith('third_party\\WebKit')):
2593 continue
2594
2595 if not CppChecker.IsCppFile(f.LocalPath()):
2596 continue
2597
Vaclav Brozekd5de76a2018-03-17 07:57:502598 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:362599 if "#include" in line and "../" in line]
2600 if not relative_includes:
2601 continue
2602 bad_files[f.LocalPath()] = relative_includes
2603
2604 if not bad_files:
2605 return []
2606
2607 error_descriptions = []
2608 for file_path, bad_lines in bad_files.iteritems():
2609 error_description = file_path
2610 for line in bad_lines:
2611 error_description += '\n ' + line
2612 error_descriptions.append(error_description)
2613
2614 results = []
2615 results.append(output_api.PresubmitError(
2616 'You added one or more relative #include paths (including "../").\n'
2617 'These shouldn\'t be used because they can be used to include headers\n'
2618 'from code that\'s not correctly specified as a dependency in the\n'
2619 'relevant BUILD.gn file(s).',
2620 error_descriptions))
2621
2622 return results
2623
Takeshi Yoshinoe387aa32017-08-02 13:16:132624
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202625def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2626 if not isinstance(key, ast.Str):
2627 return 'Key at line %d must be a string literal' % key.lineno
2628 if not isinstance(value, ast.Dict):
2629 return 'Value at line %d must be a dict' % value.lineno
2630 if len(value.keys) != 1:
2631 return 'Dict at line %d must have single entry' % value.lineno
2632 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2633 return (
2634 'Entry at line %d must have a string literal \'filepath\' as key' %
2635 value.lineno)
2636 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132637
Takeshi Yoshinoe387aa32017-08-02 13:16:132638
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202639def _CheckWatchlistsEntrySyntax(key, value, ast):
2640 if not isinstance(key, ast.Str):
2641 return 'Key at line %d must be a string literal' % key.lineno
2642 if not isinstance(value, ast.List):
2643 return 'Value at line %d must be a list' % value.lineno
2644 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132645
Takeshi Yoshinoe387aa32017-08-02 13:16:132646
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202647def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2648 mismatch_template = (
2649 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2650 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132651
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202652 i = 0
2653 last_key = ''
2654 while True:
2655 if i >= len(wd_dict.keys):
2656 if i >= len(w_dict.keys):
2657 return None
2658 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2659 elif i >= len(w_dict.keys):
2660 return (
2661 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132662
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202663 wd_key = wd_dict.keys[i]
2664 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132665
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202666 result = _CheckWatchlistDefinitionsEntrySyntax(
2667 wd_key, wd_dict.values[i], ast)
2668 if result is not None:
2669 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132670
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202671 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2672 if result is not None:
2673 return 'Bad entry in WATCHLISTS dict: %s' % result
2674
2675 if wd_key.s != w_key.s:
2676 return mismatch_template % (
2677 '%s at line %d' % (wd_key.s, wd_key.lineno),
2678 '%s at line %d' % (w_key.s, w_key.lineno))
2679
2680 if wd_key.s < last_key:
2681 return (
2682 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2683 (wd_key.lineno, w_key.lineno))
2684 last_key = wd_key.s
2685
2686 i = i + 1
2687
2688
2689def _CheckWATCHLISTSSyntax(expression, ast):
2690 if not isinstance(expression, ast.Expression):
2691 return 'WATCHLISTS file must contain a valid expression'
2692 dictionary = expression.body
2693 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2694 return 'WATCHLISTS file must have single dict with exactly two entries'
2695
2696 first_key = dictionary.keys[0]
2697 first_value = dictionary.values[0]
2698 second_key = dictionary.keys[1]
2699 second_value = dictionary.values[1]
2700
2701 if (not isinstance(first_key, ast.Str) or
2702 first_key.s != 'WATCHLIST_DEFINITIONS' or
2703 not isinstance(first_value, ast.Dict)):
2704 return (
2705 'The first entry of the dict in WATCHLISTS file must be '
2706 'WATCHLIST_DEFINITIONS dict')
2707
2708 if (not isinstance(second_key, ast.Str) or
2709 second_key.s != 'WATCHLISTS' or
2710 not isinstance(second_value, ast.Dict)):
2711 return (
2712 'The second entry of the dict in WATCHLISTS file must be '
2713 'WATCHLISTS dict')
2714
2715 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132716
2717
2718def _CheckWATCHLISTS(input_api, output_api):
2719 for f in input_api.AffectedFiles(include_deletes=False):
2720 if f.LocalPath() == 'WATCHLISTS':
2721 contents = input_api.ReadFile(f, 'r')
2722
2723 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202724 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132725 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202726 # Get an AST tree for it and scan the tree for detailed style checking.
2727 expression = input_api.ast.parse(
2728 contents, filename='WATCHLISTS', mode='eval')
2729 except ValueError as e:
2730 return [output_api.PresubmitError(
2731 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2732 except SyntaxError as e:
2733 return [output_api.PresubmitError(
2734 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2735 except TypeError as e:
2736 return [output_api.PresubmitError(
2737 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132738
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202739 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2740 if result is not None:
2741 return [output_api.PresubmitError(result)]
2742 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132743
2744 return []
2745
2746
dgnaa68d5e2015-06-10 10:08:222747def _AndroidSpecificOnUploadChecks(input_api, output_api):
2748 """Groups checks that target android code."""
2749 results = []
dgnaa68d5e2015-06-10 10:08:222750 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222751 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292752 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062753 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2754 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422755 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182756 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222757 return results
2758
2759
[email protected]22c9bd72011-03-27 16:47:392760def _CommonChecks(input_api, output_api):
2761 """Checks common to both upload and commit."""
2762 results = []
2763 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382764 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542765 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:082766
2767 author = input_api.change.author_email
2768 if author and author not in _KNOWN_ROBOTS:
2769 results.extend(
2770 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
2771
[email protected]55459852011-08-10 15:17:192772 results.extend(
[email protected]760deea2013-12-10 19:33:492773 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:232774 results.extend(
2775 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542776 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182777 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522778 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222779 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442780 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592781 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062782 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122783 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182784 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222785 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302786 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492787 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032788 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492789 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442790 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272791 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072792 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542793 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442794 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392795 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552796 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042797 results.extend(
2798 input_api.canned_checks.CheckChangeHasNoTabs(
2799 input_api,
2800 output_api,
2801 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402802 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162803 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082804 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242805 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2806 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472807 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042808 results.extend(_CheckForIPCRules(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:142809 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232810 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432811 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402812 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152813 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172814 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502815 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242816 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362817 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132818 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432819 results.extend(input_api.RunTests(
2820 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242821
Vaclav Brozekcdc7defb2018-03-20 09:54:352822 for f in input_api.AffectedFiles():
2823 path, name = input_api.os_path.split(f.LocalPath())
2824 if name == 'PRESUBMIT.py':
2825 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
2826 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2827 input_api, output_api, full_path,
2828 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392829 return results
[email protected]1f7b4172010-01-28 01:17:342830
[email protected]b337cb5b2011-01-23 21:24:052831
[email protected]b8079ae4a2012-12-05 19:56:492832def _CheckPatchFiles(input_api, output_api):
2833 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2834 if f.LocalPath().endswith(('.orig', '.rej'))]
2835 if problems:
2836 return [output_api.PresubmitError(
2837 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032838 else:
2839 return []
[email protected]b8079ae4a2012-12-05 19:56:492840
2841
Kent Tamura5a8755d2017-06-29 23:37:072842def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212843 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2844 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2845 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072846 include_re = input_api.re.compile(
2847 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2848 extension_re = input_api.re.compile(r'\.[a-z]+$')
2849 errors = []
2850 for f in input_api.AffectedFiles():
2851 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2852 continue
2853 found_line_number = None
2854 found_macro = None
2855 for line_num, line in f.ChangedContents():
2856 match = macro_re.search(line)
2857 if match:
2858 found_line_number = line_num
2859 found_macro = match.group(2)
2860 break
2861 if not found_line_number:
2862 continue
2863
2864 found_include = False
2865 for line in f.NewContents():
2866 if include_re.search(line):
2867 found_include = True
2868 break
2869 if found_include:
2870 continue
2871
2872 if not f.LocalPath().endswith('.h'):
2873 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2874 try:
2875 content = input_api.ReadFile(primary_header_path, 'r')
2876 if include_re.search(content):
2877 continue
2878 except IOError:
2879 pass
2880 errors.append('%s:%d %s macro is used without including build/'
2881 'build_config.h.'
2882 % (f.LocalPath(), found_line_number, found_macro))
2883 if errors:
2884 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2885 return []
2886
2887
[email protected]b00342e7f2013-03-26 16:21:542888def _DidYouMeanOSMacro(bad_macro):
2889 try:
2890 return {'A': 'OS_ANDROID',
2891 'B': 'OS_BSD',
2892 'C': 'OS_CHROMEOS',
2893 'F': 'OS_FREEBSD',
2894 'L': 'OS_LINUX',
2895 'M': 'OS_MACOSX',
2896 'N': 'OS_NACL',
2897 'O': 'OS_OPENBSD',
2898 'P': 'OS_POSIX',
2899 'S': 'OS_SOLARIS',
2900 'W': 'OS_WIN'}[bad_macro[3].upper()]
2901 except KeyError:
2902 return ''
2903
2904
2905def _CheckForInvalidOSMacrosInFile(input_api, f):
2906 """Check for sensible looking, totally invalid OS macros."""
2907 preprocessor_statement = input_api.re.compile(r'^\s*#')
2908 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2909 results = []
2910 for lnum, line in f.ChangedContents():
2911 if preprocessor_statement.search(line):
2912 for match in os_macro.finditer(line):
2913 if not match.group(1) in _VALID_OS_MACROS:
2914 good = _DidYouMeanOSMacro(match.group(1))
2915 did_you_mean = ' (did you mean %s?)' % good if good else ''
2916 results.append(' %s:%d %s%s' % (f.LocalPath(),
2917 lnum,
2918 match.group(1),
2919 did_you_mean))
2920 return results
2921
2922
2923def _CheckForInvalidOSMacros(input_api, output_api):
2924 """Check all affected files for invalid OS macros."""
2925 bad_macros = []
2926 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472927 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542928 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2929
2930 if not bad_macros:
2931 return []
2932
2933 return [output_api.PresubmitError(
2934 'Possibly invalid OS macro[s] found. Please fix your code\n'
2935 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2936
lliabraa35bab3932014-10-01 12:16:442937
2938def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2939 """Check all affected files for invalid "if defined" macros."""
2940 ALWAYS_DEFINED_MACROS = (
2941 "TARGET_CPU_PPC",
2942 "TARGET_CPU_PPC64",
2943 "TARGET_CPU_68K",
2944 "TARGET_CPU_X86",
2945 "TARGET_CPU_ARM",
2946 "TARGET_CPU_MIPS",
2947 "TARGET_CPU_SPARC",
2948 "TARGET_CPU_ALPHA",
2949 "TARGET_IPHONE_SIMULATOR",
2950 "TARGET_OS_EMBEDDED",
2951 "TARGET_OS_IPHONE",
2952 "TARGET_OS_MAC",
2953 "TARGET_OS_UNIX",
2954 "TARGET_OS_WIN32",
2955 )
2956 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2957 results = []
2958 for lnum, line in f.ChangedContents():
2959 for match in ifdef_macro.finditer(line):
2960 if match.group(1) in ALWAYS_DEFINED_MACROS:
2961 always_defined = ' %s is always defined. ' % match.group(1)
2962 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2963 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2964 lnum,
2965 always_defined,
2966 did_you_mean))
2967 return results
2968
2969
2970def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2971 """Check all affected files for invalid "if defined" macros."""
2972 bad_macros = []
2973 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212974 if f.LocalPath().startswith('third_party/sqlite/'):
2975 continue
lliabraa35bab3932014-10-01 12:16:442976 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2977 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2978
2979 if not bad_macros:
2980 return []
2981
2982 return [output_api.PresubmitError(
2983 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2984 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2985 bad_macros)]
2986
2987
mlamouria82272622014-09-16 18:45:042988def _CheckForIPCRules(input_api, output_api):
2989 """Check for same IPC rules described in
2990 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2991 """
2992 base_pattern = r'IPC_ENUM_TRAITS\('
2993 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2994 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2995
2996 problems = []
2997 for f in input_api.AffectedSourceFiles(None):
2998 local_path = f.LocalPath()
2999 if not local_path.endswith('.h'):
3000 continue
3001 for line_number, line in f.ChangedContents():
3002 if inclusion_pattern.search(line) and not comment_pattern.search(line):
3003 problems.append(
3004 '%s:%d\n %s' % (local_path, line_number, line.strip()))
3005
3006 if problems:
3007 return [output_api.PresubmitPromptWarning(
3008 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
3009 else:
3010 return []
3011
[email protected]b00342e7f2013-03-26 16:21:543012
Daniel Bratell8ba52722018-03-02 16:06:143013def _CheckForIncludeGuards(input_api, output_api):
3014 """Check that header files have proper guards against multiple inclusion.
3015 If a file should not have such guards (and it probably should) then it
3016 should include the string "no-include-guard-because-multiply-included".
3017 """
3018 def is_header_file(f):
3019 return f.LocalPath().endswith('.h')
3020
3021 def replace_special_with_underscore(string):
3022 return input_api.re.sub(r'[\\/.-]', '_', string)
3023
3024 errors = []
3025
3026 for f in input_api.AffectedSourceFiles(is_header_file):
3027 guard_name = None
3028 guard_line_number = None
3029 seen_guard_end = False
3030
3031 file_with_path = input_api.os_path.normpath(f.LocalPath())
3032 base_file_name = input_api.os_path.splitext(
3033 input_api.os_path.basename(file_with_path))[0]
3034 upper_base_file_name = base_file_name.upper()
3035
3036 expected_guard = replace_special_with_underscore(
3037 file_with_path.upper() + '_')
3038 expected_guard_if_blink = base_file_name + '_h'
3039
3040 # For "path/elem/file_name.h" we should really only accept
3041 # PATH_ELEM_FILE_NAME_H_ per coding style or, if Blink,
3042 # file_name_h. Unfortunately there are too many (1000+) files
3043 # with slight deviations from the coding style. Since the most
3044 # important part is that the include guard is there, and that it's
3045 # unique, not the name, this check is forgiving for existing files.
3046 #
3047 # As code becomes more uniform, this could be made stricter.
3048
3049 guard_name_pattern_list = [
3050 # Anything with the right suffix (maybe with an extra _).
3051 r'\w+_H__?',
3052
3053 # To cover include guards with Blink style.
3054 r'\w+_h',
3055
3056 # Anything including the uppercase name of the file.
3057 r'\w*' + input_api.re.escape(replace_special_with_underscore(
3058 upper_base_file_name)) + r'\w*',
3059 ]
3060 guard_name_pattern = '|'.join(guard_name_pattern_list)
3061 guard_pattern = input_api.re.compile(
3062 r'#ifndef\s+(' + guard_name_pattern + ')')
3063
3064 for line_number, line in enumerate(f.NewContents()):
3065 if 'no-include-guard-because-multiply-included' in line:
3066 guard_name = 'DUMMY' # To not trigger check outside the loop.
3067 break
3068
3069 if guard_name is None:
3070 match = guard_pattern.match(line)
3071 if match:
3072 guard_name = match.group(1)
3073 guard_line_number = line_number
3074
3075 # We allow existing files to use slightly wrong include
3076 # guards, but new files should get it right.
3077 if not f.OldContents():
3078 is_in_blink = file_with_path.startswith(input_api.os_path.join(
3079 'third_party', 'WebKit'))
3080 if not (guard_name == expected_guard or
3081 is_in_blink and guard_name == expected_guard_if_blink):
3082 if is_in_blink:
3083 expected_text = "%s or %s" % (expected_guard,
3084 expected_guard_if_blink)
3085 else:
3086 expected_text = expected_guard
3087 errors.append(output_api.PresubmitPromptWarning(
3088 'Header using the wrong include guard name %s' % guard_name,
3089 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Daniel Bratell00e1b9bc2018-03-12 13:11:123090 'Expected: %r\nFound: %r' % (expected_text, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:143091 else:
3092 # The line after #ifndef should have a #define of the same name.
3093 if line_number == guard_line_number + 1:
3094 expected_line = '#define %s' % guard_name
3095 if line != expected_line:
3096 errors.append(output_api.PresubmitPromptWarning(
3097 'Missing "%s" for include guard' % expected_line,
3098 ['%s:%d' % (f.LocalPath(), line_number + 1)],
3099 'Expected: %r\nGot: %r' % (expected_line, line)))
3100
3101 if not seen_guard_end and line == '#endif // %s' % guard_name:
3102 seen_guard_end = True
3103 elif seen_guard_end:
3104 if line.strip() != '':
3105 errors.append(output_api.PresubmitPromptWarning(
3106 'Include guard %s not covering the whole file' % (
3107 guard_name), [f.LocalPath()]))
3108 break # Nothing else to check and enough to warn once.
3109
3110 if guard_name is None:
3111 errors.append(output_api.PresubmitPromptWarning(
3112 'Missing include guard %s' % expected_guard,
3113 [f.LocalPath()],
3114 'Missing include guard in %s\n'
3115 'Recommended name: %s\n'
3116 'This check can be disabled by having the string\n'
3117 'no-include-guard-because-multiply-included in the header.' %
3118 (f.LocalPath(), expected_guard)))
3119
3120 return errors
3121
3122
mostynbb639aca52015-01-07 20:31:233123def _CheckForWindowsLineEndings(input_api, output_api):
3124 """Check source code and known ascii text files for Windows style line
3125 endings.
3126 """
earthdok1b5e0ee2015-03-10 15:19:103127 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:233128
3129 file_inclusion_pattern = (
3130 known_text_files,
3131 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3132 )
3133
mostynbb639aca52015-01-07 20:31:233134 problems = []
Andrew Grieve933d12e2017-10-30 20:22:533135 source_file_filter = lambda f: input_api.FilterSourceFile(
3136 f, white_list=file_inclusion_pattern, black_list=None)
3137 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:503138 include_file = False
3139 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:233140 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:503141 include_file = True
3142 if include_file:
3143 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:233144
3145 if problems:
3146 return [output_api.PresubmitPromptWarning('Are you sure that you want '
3147 'these files to contain Windows style line endings?\n' +
3148 '\n'.join(problems))]
3149
3150 return []
3151
3152
Vaclav Brozekd5de76a2018-03-17 07:57:503153def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:133154 """Checks that all source files use SYSLOG properly."""
3155 syslog_files = []
3156 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:563157 for line_number, line in f.ChangedContents():
3158 if 'SYSLOG' in line:
3159 syslog_files.append(f.LocalPath() + ':' + str(line_number))
3160
pastarmovj89f7ee12016-09-20 14:58:133161 if syslog_files:
3162 return [output_api.PresubmitPromptWarning(
3163 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
3164 ' calls.\nFiles to check:\n', items=syslog_files)]
3165 return []
3166
3167
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193168def _CheckCrbugLinksHaveHttps(input_api, output_api):
Miguel Casas68bdb652017-12-19 16:29:093169 """Checks that crbug(.com) links are correctly prefixed by https://,
3170 unless they come in the accepted form TODO(crbug.com/...)
3171 """
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193172 white_list = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3173 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS)
3174 sources = lambda f: input_api.FilterSourceFile(
3175 f, white_list=white_list, black_list=black_list)
3176
3177 pattern = input_api.re.compile(r'//.*(?<!:\/\/)crbug[.com]*')
Miguel Casas68bdb652017-12-19 16:29:093178 accepted_pattern = input_api.re.compile(r'//.*TODO\(crbug[.com]*');
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193179 problems = []
3180 for f in input_api.AffectedSourceFiles(sources):
3181 for line_num, line in f.ChangedContents():
Miguel Casas68bdb652017-12-19 16:29:093182 if pattern.search(line) and not accepted_pattern.search(line):
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193183 problems.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
3184
3185 if problems:
3186 return [output_api.PresubmitPromptWarning(
3187 'Found unprefixed crbug.com URL(s), consider prepending https://\n'+
3188 '\n'.join(problems))]
3189 return []
3190
3191
[email protected]1f7b4172010-01-28 01:17:343192def CheckChangeOnUpload(input_api, output_api):
3193 results = []
3194 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:473195 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:283196 results.extend(
jam93a6ee792017-02-08 23:59:223197 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:193198 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:223199 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:133200 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:163201 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193202 results.extend(_CheckCrbugLinksHaveHttps(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:533203 results.extend(_CheckUniquePtr(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543204 return results
[email protected]ca8d19842009-02-19 16:33:123205
3206
[email protected]1bfb8322014-04-23 01:02:413207def GetTryServerMasterForBot(bot):
3208 """Returns the Try Server master for the given bot.
3209
[email protected]0bb112362014-07-26 04:38:323210 It tries to guess the master from the bot name, but may still fail
3211 and return None. There is no longer a default master.
3212 """
3213 # Potentially ambiguous bot names are listed explicitly.
3214 master_map = {
tandriie5587792016-07-14 00:34:503215 'chromium_presubmit': 'master.tryserver.chromium.linux',
3216 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:413217 }
[email protected]0bb112362014-07-26 04:38:323218 master = master_map.get(bot)
3219 if not master:
wnwen4fbaab82016-05-25 12:54:363220 if 'android' in bot:
tandriie5587792016-07-14 00:34:503221 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:363222 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:503223 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:323224 elif 'win' in bot:
tandriie5587792016-07-14 00:34:503225 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:323226 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:503227 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:323228 return master
[email protected]1bfb8322014-04-23 01:02:413229
3230
[email protected]ca8d19842009-02-19 16:33:123231def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:543232 results = []
[email protected]1f7b4172010-01-28 01:17:343233 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543234 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:273235 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:343236 input_api,
3237 output_api,
[email protected]2fdd1f362013-01-16 03:56:033238 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:273239
jam93a6ee792017-02-08 23:59:223240 results.extend(
3241 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:543242 results.extend(input_api.canned_checks.CheckChangeHasBugField(
3243 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:413244 results.extend(input_api.canned_checks.CheckChangeHasDescription(
3245 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543246 return results