blob: 77cb7fa9549189827c7bc2f2042b904e231d9545 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]40d1dbb2012-10-26 07:18:0013 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
14 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2815 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0816 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5417 r"^skia[\\\/].*",
Kent Tamurae9b3a9ec2017-08-31 02:20:1918 r"^third_party[\\\/](WebKit|blink)[\\\/].*",
Mark Mentovaiebb9ddd62017-09-25 17:24:4119 r"^third_party[\\\/]breakpad[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
vapierb2053f542017-03-09 19:46:1026 r"tools[\\\/]md_browser[\\\/].*\.css$",
Kenneth Russell077c8d92017-12-16 02:52:1427 # Test pages for Maps telemetry tests.
28 r"tools[\\\/]perf[\\\/]page_sets[\\\/]maps_perf_test.*",
ehmaldonado78eee2ed2017-03-28 13:16:5429 # Test pages for WebRTC telemetry tests.
30 r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4031)
[email protected]ca8d1982009-02-19 16:33:1232
wnwenbdc444e2016-05-25 13:44:1533
[email protected]06e6d0ff2012-12-11 01:36:4434# Fragment of a regular expression that matches C++ and Objective-C++
35# implementation files.
36_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
37
wnwenbdc444e2016-05-25 13:44:1538
[email protected]06e6d0ff2012-12-11 01:36:4439# Regular expression that matches code only used for test binaries
40# (best effort).
41_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4942 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4443 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
Steven Holte27008b7422018-01-29 20:55:4444 r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1245 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4446 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0548 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4949 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4750 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4951 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0852 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4953 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4454)
[email protected]ca8d1982009-02-19 16:33:1255
wnwenbdc444e2016-05-25 13:44:1556
[email protected]eea609a2011-11-18 13:10:1257_TEST_ONLY_WARNING = (
58 'You might be calling functions intended only for testing from\n'
59 'production code. It is OK to ignore this warning if you know what\n'
60 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5861 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1262
63
[email protected]cf9b78f2012-11-14 11:40:2864_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4065 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2166 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
67 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2868
wnwenbdc444e2016-05-25 13:44:1569
Eric Stevensona9a980972017-09-23 00:04:4170_BANNED_JAVA_FUNCTIONS = (
71 (
72 'StrictMode.allowThreadDiskReads()',
73 (
74 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
75 'directly.',
76 ),
77 False,
78 ),
79 (
80 'StrictMode.allowThreadDiskWrites()',
81 (
82 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
83 'directly.',
84 ),
85 False,
86 ),
87)
88
[email protected]127f18ec2012-06-16 05:05:5989_BANNED_OBJC_FUNCTIONS = (
90 (
91 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2092 (
93 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5994 'prohibited. Please use CrTrackingArea instead.',
95 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
96 ),
97 False,
98 ),
99 (
[email protected]eaae1972014-04-16 04:17:26100 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20101 (
102 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59103 'instead.',
104 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
105 ),
106 False,
107 ),
108 (
109 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20110 (
111 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59112 'Please use |convertPoint:(point) fromView:nil| instead.',
113 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
114 ),
115 True,
116 ),
117 (
118 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20119 (
120 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59121 'Please use |convertPoint:(point) toView:nil| instead.',
122 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
123 ),
124 True,
125 ),
126 (
127 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20128 (
129 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59130 'Please use |convertRect:(point) fromView:nil| instead.',
131 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
132 ),
133 True,
134 ),
135 (
136 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20137 (
138 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59139 'Please use |convertRect:(point) toView:nil| instead.',
140 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
141 ),
142 True,
143 ),
144 (
145 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20146 (
147 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59148 'Please use |convertSize:(point) fromView:nil| instead.',
149 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
150 ),
151 True,
152 ),
153 (
154 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20155 (
156 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59157 'Please use |convertSize:(point) toView:nil| instead.',
158 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
159 ),
160 True,
161 ),
jif65398702016-10-27 10:19:48162 (
163 r"/\s+UTF8String\s*]",
164 (
165 'The use of -[NSString UTF8String] is dangerous as it can return null',
166 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
167 'Please use |SysNSStringToUTF8| instead.',
168 ),
169 True,
170 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34171 (
172 r'__unsafe_unretained',
173 (
174 'The use of __unsafe_unretained is almost certainly wrong, unless',
175 'when interacting with NSFastEnumeration or NSInvocation.',
176 'Please use __weak in files build with ARC, nothing otherwise.',
177 ),
178 False,
179 ),
[email protected]127f18ec2012-06-16 05:05:59180)
181
Sylvain Defresnea8b73d252018-02-28 15:45:54182_BANNED_IOS_OBJC_FUNCTIONS = (
183 (
184 r'/\bTEST[(]',
185 (
186 'TEST() macro should not be used in Objective-C++ code as it does not ',
187 'drain the autorelease pool at the end of the test. Use TEST_F() ',
188 'macro instead with a fixture inheriting from PlatformTest (or a ',
189 'typedef).'
190 ),
191 True,
192 ),
193 (
194 r'/\btesting::Test\b',
195 (
196 'testing::Test should not be used in Objective-C++ code as it does ',
197 'not drain the autorelease pool at the end of the test. Use ',
198 'PlatformTest instead.'
199 ),
200 True,
201 ),
202)
203
[email protected]127f18ec2012-06-16 05:05:59204
205_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20206 # Make sure that gtest's FRIEND_TEST() macro is not used; the
207 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30208 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20209 (
thomasandersone7caaa9b2017-03-29 19:22:53210 r'\bNULL\b',
211 (
212 'New code should not use NULL. Use nullptr instead.',
213 ),
214 True,
215 (),
216 ),
217 (
[email protected]23e6cbc2012-06-16 18:51:20218 'FRIEND_TEST(',
219 (
[email protected]e3c945502012-06-26 20:01:49220 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20221 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
222 ),
223 False,
[email protected]7345da02012-11-27 14:31:49224 (),
[email protected]23e6cbc2012-06-16 18:51:20225 ),
226 (
thomasanderson4b569052016-09-14 20:15:53227 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
228 (
229 'Chrome clients wishing to select events on X windows should use',
230 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
231 'you are selecting events from the GPU process, or if you are using',
232 'an XDisplay other than gfx::GetXDisplay().',
233 ),
234 True,
235 (
236 r"^ui[\\\/]gl[\\\/].*\.cc$",
237 r"^media[\\\/]gpu[\\\/].*\.cc$",
238 r"^gpu[\\\/].*\.cc$",
239 ),
240 ),
241 (
thomasandersone043e3ce2017-06-08 00:43:20242 r'XInternAtom|xcb_intern_atom',
243 (
thomasanderson11aa41d2017-06-08 22:22:38244 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20245 ),
246 True,
247 (
thomasanderson11aa41d2017-06-08 22:22:38248 r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$",
249 r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20250 r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$",
251 ),
252 ),
253 (
tomhudsone2c14d552016-05-26 17:07:46254 'setMatrixClip',
255 (
256 'Overriding setMatrixClip() is prohibited; ',
257 'the base function is deprecated. ',
258 ),
259 True,
260 (),
261 ),
262 (
[email protected]52657f62013-05-20 05:30:31263 'SkRefPtr',
264 (
265 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22266 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31267 ),
268 True,
269 (),
270 ),
271 (
272 'SkAutoRef',
273 (
274 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22275 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31276 ),
277 True,
278 (),
279 ),
280 (
281 'SkAutoTUnref',
282 (
283 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22284 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31285 ),
286 True,
287 (),
288 ),
289 (
290 'SkAutoUnref',
291 (
292 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
293 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22294 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31295 ),
296 True,
297 (),
298 ),
[email protected]d89eec82013-12-03 14:10:59299 (
300 r'/HANDLE_EINTR\(.*close',
301 (
302 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
303 'descriptor will be closed, and it is incorrect to retry the close.',
304 'Either call close directly and ignore its return value, or wrap close',
305 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
306 ),
307 True,
308 (),
309 ),
310 (
311 r'/IGNORE_EINTR\((?!.*close)',
312 (
313 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
314 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
315 ),
316 True,
317 (
318 # Files that #define IGNORE_EINTR.
319 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
320 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
321 ),
322 ),
[email protected]ec5b3f02014-04-04 18:43:43323 (
324 r'/v8::Extension\(',
325 (
326 'Do not introduce new v8::Extensions into the code base, use',
327 'gin::Wrappable instead. See http://crbug.com/334679',
328 ),
329 True,
[email protected]f55c90ee62014-04-12 00:50:03330 (
joaodasilva718f87672014-08-30 09:25:49331 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03332 ),
[email protected]ec5b3f02014-04-04 18:43:43333 ),
skyostilf9469f72015-04-20 10:38:52334 (
jame2d1a952016-04-02 00:27:10335 '#pragma comment(lib,',
336 (
337 'Specify libraries to link with in build files and not in the source.',
338 ),
339 True,
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',
Chris Mumford8d26d10a2018-04-20 17:07:58405 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
406 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08407 ),
408 True,
409 (
410 r'^third_party/leveldatabase/.*\.(cc|h)$',
411 ),
412 ),
413 (
Gabriel Charetted9839bc2017-07-29 14:17:47414 'MessageLoop::QuitWhenIdleClosure',
Gabriel Charette0592c3a2017-07-26 12:02:04415 (
Peter Kasting9e7ccfa52018-02-06 00:01:20416 'MessageLoop::QuitWhenIdleClosure is deprecated. Please use a',
417 'QuitWhenIdleClosure obtained from a specific RunLoop instance.',
Gabriel Charette0592c3a2017-07-26 12:02:04418 ),
Peter Kasting9e7ccfa52018-02-06 00:01:20419 False,
Gabriel Charette0592c3a2017-07-26 12:02:04420 (),
Gabriel Charetted9839bc2017-07-29 14:17:47421 ),
422 (
423 'RunLoop::QuitCurrent',
424 (
Robert Liao64b7ab22017-08-04 23:03:43425 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
426 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47427 ),
428 True,
429 (),
Gabriel Charettea44975052017-08-21 23:14:04430 ),
431 (
432 'base::ScopedMockTimeMessageLoopTaskRunner',
433 (
434 'ScopedMockTimeMessageLoopTaskRunner is deprecated.',
435 ),
436 True,
437 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57438 ),
439 (
440 r'std::regex',
441 (
442 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02443 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57444 ),
445 True,
446 (),
Francois Doray43670e32017-09-27 12:40:38447 ),
448 (
449 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
450 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
451 (
452 'Use the new API in base/threading/thread_restrictions.h.',
453 ),
454 True,
455 (),
456 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38457 (
458 r'/\bbase::Bind\(',
459 (
Gabriel Charette147335ea2018-03-22 15:59:19460 'Please consider using base::Bind{Once,Repeating} instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02461 'of base::Bind. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38462 ),
463 False,
464 (),
465 ),
466 (
467 r'/\bbase::Callback<',
468 (
Gabriel Charette147335ea2018-03-22 15:59:19469 'Please consider using base::{Once,Repeating}Callback instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02470 'of base::Callback. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38471 ),
472 False,
473 (),
474 ),
475 (
476 r'/\bbase::Closure\b',
477 (
Gabriel Charette147335ea2018-03-22 15:59:19478 'Please consider using base::{Once,Repeating}Closure instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02479 'of base::Closure. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38480 ),
481 False,
482 (),
483 ),
Victor Costan3653df62018-02-08 21:38:16484 (
Gabriel Charette147335ea2018-03-22 15:59:19485 r'RunMessageLoop',
486 (
487 'RunMessageLoop is deprecated, use RunLoop instead.',
488 ),
489 False,
490 (),
491 ),
492 (
493 r'RunThisRunLoop',
494 (
495 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
496 ),
497 False,
498 (),
499 ),
500 (
501 r'RunAllPendingInMessageLoop()',
502 (
503 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
504 "if you're convinced you need this.",
505 ),
506 False,
507 (),
508 ),
509 (
510 r'RunAllPendingInMessageLoop(BrowserThread',
511 (
512 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
513 'BrowserThread::UI, TestBrowserThreadBundle::RunIOThreadUntilIdle',
514 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
515 'async events instead of flushing threads.',
516 ),
517 False,
518 (),
519 ),
520 (
521 r'MessageLoopRunner',
522 (
523 'MessageLoopRunner is deprecated, use RunLoop instead.',
524 ),
525 False,
526 (),
527 ),
528 (
529 r'GetDeferredQuitTaskForRunLoop',
530 (
531 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
532 "gab@ if you found a use case where this is the only solution.",
533 ),
534 False,
535 (),
536 ),
537 (
Victor Costan3653df62018-02-08 21:38:16538 'sqlite3_initialize',
539 (
540 'Instead of sqlite3_initialize, depend on //sql, ',
541 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
542 ),
543 True,
544 (
545 r'^sql/initialization\.(cc|h)$',
546 r'^third_party/sqlite/.*\.(c|cc|h)$',
547 ),
548 ),
Matt Menke7f520a82018-03-28 21:38:37549 (
550 'net::URLFetcher',
551 (
552 'net::URLFetcher should no longer be used in content embedders. ',
553 'Instead, use network::SimpleURLLoader instead, which supports ',
554 'an out-of-process network stack. ',
555 'net::URLFetcher may still be used in binaries that do not embed',
556 'content.',
557 ),
Matt Menke59716d02018-04-05 12:45:53558 False,
Matt Menke7f520a82018-03-28 21:38:37559 (
560 r'^ios[\\\/].*\.(cc|h)$',
561 r'.*[\\\/]ios[\\\/].*\.(cc|h)$',
562 r'.*_ios\.(cc|h)$',
563 r'^net[\\\/].*\.(cc|h)$',
564 r'.*[\\\/]tools[\\\/].*\.(cc|h)$',
565 ),
566 ),
[email protected]127f18ec2012-06-16 05:05:59567)
568
wnwenbdc444e2016-05-25 13:44:15569
mlamouria82272622014-09-16 18:45:04570_IPC_ENUM_TRAITS_DEPRECATED = (
571 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50572 'See http://www.chromium.org/Home/chromium-security/education/'
573 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:04574
Shenghua Zhangbfaa38b82017-11-16 21:58:02575_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
576 r".*[\\\/]BuildHooksAndroidImpl\.java",
577 r".*[\\\/]LicenseContentProvider\.java",
578]
[email protected]127f18ec2012-06-16 05:05:59579
Sean Kau46e29bc2017-08-28 16:31:16580# These paths contain test data and other known invalid JSON files.
581_KNOWN_INVALID_JSON_FILE_PATTERNS = [
582 r'test[\\\/]data[\\\/]',
583 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
584 r'^third_party[\\\/]protobuf[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16585 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Alexey Kozyatinskiya42a629f2018-04-17 17:49:38586 r'^third_party[\\\/]blink[\\\/]renderer[\\\/]devtools[\\\/]protocol\.json$',
Sean Kau46e29bc2017-08-28 16:31:16587]
588
589
[email protected]b00342e7f2013-03-26 16:21:54590_VALID_OS_MACROS = (
591 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08592 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54593 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:12594 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:54595 'OS_BSD',
596 'OS_CAT', # For testing.
597 'OS_CHROMEOS',
598 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37599 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54600 'OS_IOS',
601 'OS_LINUX',
602 'OS_MACOSX',
603 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21604 'OS_NACL_NONSFI',
605 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12606 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54607 'OS_OPENBSD',
608 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37609 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54610 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54611 'OS_WIN',
612)
613
614
agrievef32bcc72016-04-04 14:57:40615_ANDROID_SPECIFIC_PYDEPS_FILES = [
616 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04617 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58618 'build/secondary/third_party/android_platform/'
619 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19620 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40621]
622
wnwenbdc444e2016-05-25 13:44:15623
agrievef32bcc72016-04-04 14:57:40624_GENERIC_PYDEPS_FILES = [
John Chencde89192018-01-27 21:18:40625 'chrome/test/chromedriver/test/run_py_tests.pydeps',
agrievef32bcc72016-04-04 14:57:40626]
627
wnwenbdc444e2016-05-25 13:44:15628
agrievef32bcc72016-04-04 14:57:40629_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
630
631
Eric Boren6fd2b932018-01-25 15:05:08632# Bypass the AUTHORS check for these accounts.
633_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:29634 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
635 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
636 'fuchsia-sdk', 'nacl', 'pdfium', 'skia', 'src-internal', 'webrtc')
637 ) | set('%[email protected]' % s for s in ('findit-for-me',))
Eric Boren6fd2b932018-01-25 15:05:08638
639
[email protected]55459852011-08-10 15:17:19640def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
641 """Attempts to prevent use of functions intended only for testing in
642 non-testing code. For now this is just a best-effort implementation
643 that ignores header files and may have some false positives. A
644 better implementation would probably need a proper C++ parser.
645 """
646 # We only scan .cc files and the like, as the declaration of
647 # for-testing functions in header files are hard to distinguish from
648 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44649 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19650
jochenc0d4808c2015-07-27 09:25:42651 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19652 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09653 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19654 exclusion_pattern = input_api.re.compile(
655 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
656 base_function_pattern, base_function_pattern))
657
658 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44659 black_list = (_EXCLUDED_PATHS +
660 _TEST_CODE_EXCLUDED_PATHS +
661 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19662 return input_api.FilterSourceFile(
663 affected_file,
664 white_list=(file_inclusion_pattern, ),
665 black_list=black_list)
666
667 problems = []
668 for f in input_api.AffectedSourceFiles(FilterFile):
669 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24670 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03671 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46672 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03673 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19674 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03675 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19676
677 if problems:
[email protected]f7051d52013-04-02 18:31:42678 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03679 else:
680 return []
[email protected]55459852011-08-10 15:17:19681
682
Vaclav Brozek7dbc28c2018-03-27 08:35:23683def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
684 """This is a simplified version of
685 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
686 """
687 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
688 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
689 name_pattern = r'ForTest(s|ing)?'
690 # Describes an occurrence of "ForTest*" inside a // comment.
691 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
692 # Catch calls.
693 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
694 # Ignore definitions. (Comments are ignored separately.)
695 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
696
697 problems = []
698 sources = lambda x: input_api.FilterSourceFile(
699 x,
700 black_list=(('(?i).*test', r'.*\/junit\/')
701 + input_api.DEFAULT_BLACK_LIST),
702 white_list=(r'.*\.java$',)
703 )
704 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
705 local_path = f.LocalPath()
706 is_inside_javadoc = False
707 for line_number, line in f.ChangedContents():
708 if is_inside_javadoc and javadoc_end_re.search(line):
709 is_inside_javadoc = False
710 if not is_inside_javadoc and javadoc_start_re.search(line):
711 is_inside_javadoc = True
712 if is_inside_javadoc:
713 continue
714 if (inclusion_re.search(line) and
715 not comment_re.search(line) and
716 not exclusion_re.search(line)):
717 problems.append(
718 '%s:%d\n %s' % (local_path, line_number, line.strip()))
719
720 if problems:
721 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
722 else:
723 return []
724
725
[email protected]10689ca2011-09-02 02:31:54726def _CheckNoIOStreamInHeaders(input_api, output_api):
727 """Checks to make sure no .h files include <iostream>."""
728 files = []
729 pattern = input_api.re.compile(r'^#include\s*<iostream>',
730 input_api.re.MULTILINE)
731 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
732 if not f.LocalPath().endswith('.h'):
733 continue
734 contents = input_api.ReadFile(f)
735 if pattern.search(contents):
736 files.append(f)
737
738 if len(files):
yolandyandaabc6d2016-04-18 18:29:39739 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06740 'Do not #include <iostream> in header files, since it inserts static '
741 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54742 '#include <ostream>. See http://crbug.com/94794',
743 files) ]
744 return []
745
746
[email protected]72df4e782012-06-21 16:28:18747def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52748 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18749 problems = []
750 for f in input_api.AffectedFiles():
751 if (not f.LocalPath().endswith(('.cc', '.mm'))):
752 continue
753
754 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04755 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18756 problems.append(' %s:%d' % (f.LocalPath(), line_num))
757
758 if not problems:
759 return []
760 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
761 '\n'.join(problems))]
762
763
danakj61c1aa22015-10-26 19:55:52764def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57765 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52766 errors = []
767 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
768 input_api.re.MULTILINE)
769 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
770 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
771 continue
772 for lnum, line in f.ChangedContents():
773 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17774 errors.append(output_api.PresubmitError(
775 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57776 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17777 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52778 return errors
779
780
mcasasb7440c282015-02-04 14:52:19781def _FindHistogramNameInLine(histogram_name, line):
782 """Tries to find a histogram name or prefix in a line."""
783 if not "affected-histogram" in line:
784 return histogram_name in line
785 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
786 # the histogram_name.
787 if not '"' in line:
788 return False
789 histogram_prefix = line.split('\"')[1]
790 return histogram_prefix in histogram_name
791
792
793def _CheckUmaHistogramChanges(input_api, output_api):
794 """Check that UMA histogram names in touched lines can still be found in other
795 lines of the patch or in histograms.xml. Note that this check would not catch
796 the reverse: changes in histograms.xml not matched in the code itself."""
797 touched_histograms = []
798 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:47799 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
800 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
801 name_pattern = r'"(.*?)"'
802 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
803 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
804 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
805 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
806 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:17807 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:19808 for f in input_api.AffectedFiles():
809 # If histograms.xml itself is modified, keep the modified lines for later.
810 if f.LocalPath().endswith(('histograms.xml')):
811 histograms_xml_modifications = f.ChangedContents()
812 continue
Vaclav Brozekbdac817c2018-03-24 06:30:47813 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
814 single_line_re = single_line_c_re
815 split_line_prefix_re = split_line_c_prefix_re
816 elif f.LocalPath().endswith(('java')):
817 single_line_re = single_line_java_re
818 split_line_prefix_re = split_line_java_prefix_re
819 else:
mcasasb7440c282015-02-04 14:52:19820 continue
821 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:17822 if last_line_matched_prefix:
823 suffix_found = split_line_suffix_re.search(line)
824 if suffix_found :
825 touched_histograms.append([suffix_found.group(1), f, line_num])
826 last_line_matched_prefix = False
827 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:06828 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:19829 if found:
830 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:17831 continue
832 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:19833
834 # Search for the touched histogram names in the local modifications to
835 # histograms.xml, and, if not found, on the base histograms.xml file.
836 unmatched_histograms = []
837 for histogram_info in touched_histograms:
838 histogram_name_found = False
839 for line_num, line in histograms_xml_modifications:
840 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
841 if histogram_name_found:
842 break
843 if not histogram_name_found:
844 unmatched_histograms.append(histogram_info)
845
eromanb90c82e7e32015-04-01 15:13:49846 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19847 problems = []
848 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49849 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19850 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45851 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19852 histogram_name_found = False
853 for line in histograms_xml:
854 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
855 if histogram_name_found:
856 break
857 if not histogram_name_found:
858 problems.append(' [%s:%d] %s' %
859 (f.LocalPath(), line_num, histogram_name))
860
861 if not problems:
862 return []
863 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
864 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49865 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19866
wnwenbdc444e2016-05-25 13:44:15867
yolandyandaabc6d2016-04-18 18:29:39868def _CheckFlakyTestUsage(input_api, output_api):
869 """Check that FlakyTest annotation is our own instead of the android one"""
870 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
871 files = []
872 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
873 if f.LocalPath().endswith('Test.java'):
874 if pattern.search(input_api.ReadFile(f)):
875 files.append(f)
876 if len(files):
877 return [output_api.PresubmitError(
878 'Use org.chromium.base.test.util.FlakyTest instead of '
879 'android.test.FlakyTest',
880 files)]
881 return []
mcasasb7440c282015-02-04 14:52:19882
wnwenbdc444e2016-05-25 13:44:15883
[email protected]8ea5d4b2011-09-13 21:49:22884def _CheckNoNewWStrings(input_api, output_api):
885 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27886 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22887 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20888 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57889 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34890 '/win/' in f.LocalPath() or
891 'chrome_elf' in f.LocalPath() or
892 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20893 continue
[email protected]8ea5d4b2011-09-13 21:49:22894
[email protected]a11dbe9b2012-08-07 01:32:58895 allowWString = False
[email protected]b5c24292011-11-28 14:38:20896 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58897 if 'presubmit: allow wstring' in line:
898 allowWString = True
899 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27900 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58901 allowWString = False
902 else:
903 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22904
[email protected]55463aa62011-10-12 00:48:27905 if not problems:
906 return []
907 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58908 ' If you are calling a cross-platform API that accepts a wstring, '
909 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27910 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22911
912
[email protected]2a8ac9c2011-10-19 17:20:44913def _CheckNoDEPSGIT(input_api, output_api):
914 """Make sure .DEPS.git is never modified manually."""
915 if any(f.LocalPath().endswith('.DEPS.git') for f in
916 input_api.AffectedFiles()):
917 return [output_api.PresubmitError(
918 'Never commit changes to .DEPS.git. This file is maintained by an\n'
919 'automated system based on what\'s in DEPS and your changes will be\n'
920 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50921 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
922 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:44923 'for more information')]
924 return []
925
926
tandriief664692014-09-23 14:51:47927def _CheckValidHostsInDEPS(input_api, output_api):
928 """Checks that DEPS file deps are from allowed_hosts."""
929 # Run only if DEPS file has been modified to annoy fewer bystanders.
930 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
931 return []
932 # Outsource work to gclient verify
933 try:
934 input_api.subprocess.check_output(['gclient', 'verify'])
935 return []
936 except input_api.subprocess.CalledProcessError, error:
937 return [output_api.PresubmitError(
938 'DEPS file must have only git dependencies.',
939 long_text=error.output)]
940
941
[email protected]127f18ec2012-06-16 05:05:59942def _CheckNoBannedFunctions(input_api, output_api):
943 """Make sure that banned functions are not used."""
944 warnings = []
945 errors = []
946
wnwenbdc444e2016-05-25 13:44:15947 def IsBlacklisted(affected_file, blacklist):
948 local_path = affected_file.LocalPath()
949 for item in blacklist:
950 if input_api.re.match(item, local_path):
951 return True
952 return False
953
Sylvain Defresnea8b73d252018-02-28 15:45:54954 def IsIosObcjFile(affected_file):
955 local_path = affected_file.LocalPath()
956 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
957 return False
958 basename = input_api.os_path.basename(local_path)
959 if 'ios' in basename.split('_'):
960 return True
961 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
962 if sep and 'ios' in local_path.split(sep):
963 return True
964 return False
965
wnwenbdc444e2016-05-25 13:44:15966 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
967 matched = False
968 if func_name[0:1] == '/':
969 regex = func_name[1:]
970 if input_api.re.search(regex, line):
971 matched = True
972 elif func_name in line:
dchenge07de812016-06-20 19:27:17973 matched = True
wnwenbdc444e2016-05-25 13:44:15974 if matched:
dchenge07de812016-06-20 19:27:17975 problems = warnings
wnwenbdc444e2016-05-25 13:44:15976 if error:
dchenge07de812016-06-20 19:27:17977 problems = errors
wnwenbdc444e2016-05-25 13:44:15978 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
979 for message_line in message:
980 problems.append(' %s' % message_line)
981
Eric Stevensona9a980972017-09-23 00:04:41982 file_filter = lambda f: f.LocalPath().endswith(('.java'))
983 for f in input_api.AffectedFiles(file_filter=file_filter):
984 for line_num, line in f.ChangedContents():
985 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
986 CheckForMatch(f, line_num, line, func_name, message, error)
987
[email protected]127f18ec2012-06-16 05:05:59988 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
989 for f in input_api.AffectedFiles(file_filter=file_filter):
990 for line_num, line in f.ChangedContents():
991 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15992 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59993
Sylvain Defresnea8b73d252018-02-28 15:45:54994 for f in input_api.AffectedFiles(file_filter=IsIosObcjFile):
995 for line_num, line in f.ChangedContents():
996 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
997 CheckForMatch(f, line_num, line, func_name, message, error)
998
[email protected]127f18ec2012-06-16 05:05:59999 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1000 for f in input_api.AffectedFiles(file_filter=file_filter):
1001 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491002 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491003 if IsBlacklisted(f, excluded_paths):
1004 continue
wnwenbdc444e2016-05-25 13:44:151005 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591006
1007 result = []
1008 if (warnings):
1009 result.append(output_api.PresubmitPromptWarning(
1010 'Banned functions were used.\n' + '\n'.join(warnings)))
1011 if (errors):
1012 result.append(output_api.PresubmitError(
1013 'Banned functions were used.\n' + '\n'.join(errors)))
1014 return result
1015
1016
[email protected]6c063c62012-07-11 19:11:061017def _CheckNoPragmaOnce(input_api, output_api):
1018 """Make sure that banned functions are not used."""
1019 files = []
1020 pattern = input_api.re.compile(r'^#pragma\s+once',
1021 input_api.re.MULTILINE)
1022 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1023 if not f.LocalPath().endswith('.h'):
1024 continue
1025 contents = input_api.ReadFile(f)
1026 if pattern.search(contents):
1027 files.append(f)
1028
1029 if files:
1030 return [output_api.PresubmitError(
1031 'Do not use #pragma once in header files.\n'
1032 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1033 files)]
1034 return []
1035
[email protected]127f18ec2012-06-16 05:05:591036
[email protected]e7479052012-09-19 00:26:121037def _CheckNoTrinaryTrueFalse(input_api, output_api):
1038 """Checks to make sure we don't introduce use of foo ? true : false."""
1039 problems = []
1040 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1041 for f in input_api.AffectedFiles():
1042 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1043 continue
1044
1045 for line_num, line in f.ChangedContents():
1046 if pattern.match(line):
1047 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1048
1049 if not problems:
1050 return []
1051 return [output_api.PresubmitPromptWarning(
1052 'Please consider avoiding the "? true : false" pattern if possible.\n' +
1053 '\n'.join(problems))]
1054
1055
[email protected]55f9f382012-07-31 11:02:181056def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:281057 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:181058 change. Breaking - rules is an error, breaking ! rules is a
1059 warning.
1060 """
mohan.reddyf21db962014-10-16 12:26:471061 import sys
[email protected]55f9f382012-07-31 11:02:181062 # We need to wait until we have an input_api object and use this
1063 # roundabout construct to import checkdeps because this file is
1064 # eval-ed and thus doesn't have __file__.
1065 original_sys_path = sys.path
1066 try:
1067 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:471068 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:181069 import checkdeps
1070 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:241071 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:281072 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:181073 from rules import Rule
1074 finally:
1075 # Restore sys.path to what it was before.
1076 sys.path = original_sys_path
1077
1078 added_includes = []
rhalavati08acd232017-04-03 07:23:281079 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:241080 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:181081 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:281082 if CppChecker.IsCppFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501083 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081084 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:281085 elif ProtoChecker.IsProtoFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501086 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081087 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:241088 elif JavaChecker.IsJavaFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501089 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081090 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:181091
[email protected]26385172013-05-09 23:11:351092 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181093
1094 error_descriptions = []
1095 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:281096 error_subjects = set()
1097 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:181098 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
1099 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:081100 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181101 description_with_path = '%s\n %s' % (path, rule_description)
1102 if rule_type == Rule.DISALLOW:
1103 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281104 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:181105 else:
1106 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281107 warning_subjects.add("#includes")
1108
1109 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
1110 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:081111 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:281112 description_with_path = '%s\n %s' % (path, rule_description)
1113 if rule_type == Rule.DISALLOW:
1114 error_descriptions.append(description_with_path)
1115 error_subjects.add("imports")
1116 else:
1117 warning_descriptions.append(description_with_path)
1118 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:181119
Jinsuk Kim5a092672017-10-24 22:42:241120 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:021121 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:081122 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:241123 description_with_path = '%s\n %s' % (path, rule_description)
1124 if rule_type == Rule.DISALLOW:
1125 error_descriptions.append(description_with_path)
1126 error_subjects.add("imports")
1127 else:
1128 warning_descriptions.append(description_with_path)
1129 warning_subjects.add("imports")
1130
[email protected]55f9f382012-07-31 11:02:181131 results = []
1132 if error_descriptions:
1133 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:281134 'You added one or more %s that violate checkdeps rules.'
1135 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:181136 error_descriptions))
1137 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:421138 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:281139 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:181140 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:281141 '%s? See relevant DEPS file(s) for details and contacts.' %
1142 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:181143 warning_descriptions))
1144 return results
1145
1146
[email protected]fbcafe5a2012-08-08 15:31:221147def _CheckFilePermissions(input_api, output_api):
1148 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:151149 if input_api.platform == 'win32':
1150 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:291151 checkperms_tool = input_api.os_path.join(
1152 input_api.PresubmitLocalPath(),
1153 'tools', 'checkperms', 'checkperms.py')
1154 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:471155 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:391156 with input_api.CreateTemporaryFile() as file_list:
1157 for f in input_api.AffectedFiles():
1158 # checkperms.py file/directory arguments must be relative to the
1159 # repository.
1160 file_list.write(f.LocalPath() + '\n')
1161 file_list.close()
1162 args += ['--file-list', file_list.name]
1163 try:
1164 input_api.subprocess.check_output(args)
1165 return []
1166 except input_api.subprocess.CalledProcessError as error:
1167 return [output_api.PresubmitError(
1168 'checkperms.py failed:',
1169 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:221170
1171
robertocn832f5992017-01-04 19:01:301172def _CheckTeamTags(input_api, output_api):
1173 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
1174 checkteamtags_tool = input_api.os_path.join(
1175 input_api.PresubmitLocalPath(),
1176 'tools', 'checkteamtags', 'checkteamtags.py')
1177 args = [input_api.python_executable, checkteamtags_tool,
1178 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:221179 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:301180 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
1181 'OWNERS']
1182 try:
1183 if files:
1184 input_api.subprocess.check_output(args + files)
1185 return []
1186 except input_api.subprocess.CalledProcessError as error:
1187 return [output_api.PresubmitError(
1188 'checkteamtags.py failed:',
1189 long_text=error.output)]
1190
1191
[email protected]c8278b32012-10-30 20:35:491192def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
1193 """Makes sure we don't include ui/aura/window_property.h
1194 in header files.
1195 """
1196 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1197 errors = []
1198 for f in input_api.AffectedFiles():
1199 if not f.LocalPath().endswith('.h'):
1200 continue
1201 for line_num, line in f.ChangedContents():
1202 if pattern.match(line):
1203 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1204
1205 results = []
1206 if errors:
1207 results.append(output_api.PresubmitError(
1208 'Header files should not include ui/aura/window_property.h', errors))
1209 return results
1210
1211
[email protected]70ca77752012-11-20 03:45:031212def _CheckForVersionControlConflictsInFile(input_api, f):
1213 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1214 errors = []
1215 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231216 if f.LocalPath().endswith('.md'):
1217 # First-level headers in markdown look a lot like version control
1218 # conflict markers. http://daringfireball.net/projects/markdown/basics
1219 continue
[email protected]70ca77752012-11-20 03:45:031220 if pattern.match(line):
1221 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1222 return errors
1223
1224
1225def _CheckForVersionControlConflicts(input_api, output_api):
1226 """Usually this is not intentional and will cause a compile failure."""
1227 errors = []
1228 for f in input_api.AffectedFiles():
1229 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1230
1231 results = []
1232 if errors:
1233 results.append(output_api.PresubmitError(
1234 'Version control conflict markers found, please resolve.', errors))
1235 return results
1236
estadee17314a02017-01-12 16:22:161237def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1238 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1239 errors = []
1240 for f in input_api.AffectedFiles():
1241 for line_num, line in f.ChangedContents():
1242 if pattern.search(line):
1243 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1244
1245 results = []
1246 if errors:
1247 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:501248 'Found Google support URL addressed by answer number. Please replace '
1249 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:161250 return results
1251
[email protected]70ca77752012-11-20 03:45:031252
[email protected]06e6d0ff2012-12-11 01:36:441253def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1254 def FilterFile(affected_file):
1255 """Filter function for use with input_api.AffectedSourceFiles,
1256 below. This filters out everything except non-test files from
1257 top-level directories that generally speaking should not hard-code
1258 service URLs (e.g. src/android_webview/, src/content/ and others).
1259 """
1260 return input_api.FilterSourceFile(
1261 affected_file,
[email protected]78bb39d62012-12-11 15:11:561262 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441263 black_list=(_EXCLUDED_PATHS +
1264 _TEST_CODE_EXCLUDED_PATHS +
1265 input_api.DEFAULT_BLACK_LIST))
1266
reillyi38965732015-11-16 18:27:331267 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1268 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461269 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1270 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441271 problems = [] # items are (filename, line_number, line)
1272 for f in input_api.AffectedSourceFiles(FilterFile):
1273 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461274 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441275 problems.append((f.LocalPath(), line_num, line))
1276
1277 if problems:
[email protected]f7051d52013-04-02 18:31:421278 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441279 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581280 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441281 [' %s:%d: %s' % (
1282 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031283 else:
1284 return []
[email protected]06e6d0ff2012-12-11 01:36:441285
1286
[email protected]d2530012013-01-25 16:39:271287def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1288 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311289 The native_client_sdk directory is excluded because it has auto-generated PNG
1290 files for documentation.
[email protected]d2530012013-01-25 16:39:271291 """
[email protected]d2530012013-01-25 16:39:271292 errors = []
binji0dcdf342014-12-12 18:32:311293 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1294 black_list = (r'^native_client_sdk[\\\/]',)
1295 file_filter = lambda f: input_api.FilterSourceFile(
1296 f, white_list=white_list, black_list=black_list)
1297 for f in input_api.AffectedFiles(include_deletes=False,
1298 file_filter=file_filter):
1299 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271300
1301 results = []
1302 if errors:
1303 results.append(output_api.PresubmitError(
1304 'The name of PNG files should not have abbreviations. \n'
1305 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1306 'Contact [email protected] if you have questions.', errors))
1307 return results
1308
1309
Daniel Cheng4dcdb6b2017-04-13 08:30:171310def _ExtractAddRulesFromParsedDeps(parsed_deps):
1311 """Extract the rules that add dependencies from a parsed DEPS file.
1312
1313 Args:
1314 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1315 add_rules = set()
1316 add_rules.update([
1317 rule[1:] for rule in parsed_deps.get('include_rules', [])
1318 if rule.startswith('+') or rule.startswith('!')
1319 ])
Vaclav Brozekd5de76a2018-03-17 07:57:501320 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:171321 {}).iteritems():
1322 add_rules.update([
1323 rule[1:] for rule in rules
1324 if rule.startswith('+') or rule.startswith('!')
1325 ])
1326 return add_rules
1327
1328
1329def _ParseDeps(contents):
1330 """Simple helper for parsing DEPS files."""
1331 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171332 class _VarImpl:
1333
1334 def __init__(self, local_scope):
1335 self._local_scope = local_scope
1336
1337 def Lookup(self, var_name):
1338 """Implements the Var syntax."""
1339 try:
1340 return self._local_scope['vars'][var_name]
1341 except KeyError:
1342 raise Exception('Var is not defined: %s' % var_name)
1343
1344 local_scope = {}
1345 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171346 'Var': _VarImpl(local_scope).Lookup,
1347 }
1348 exec contents in global_scope, local_scope
1349 return local_scope
1350
1351
1352def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081353 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411354 a set of DEPS entries that we should look up.
1355
1356 For a directory (rather than a specific filename) we fake a path to
1357 a specific filename by adding /DEPS. This is chosen as a file that
1358 will seldom or never be subject to per-file include_rules.
1359 """
[email protected]2b438d62013-11-14 17:54:141360 # We ignore deps entries on auto-generated directories.
1361 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081362
Daniel Cheng4dcdb6b2017-04-13 08:30:171363 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1364 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1365
1366 added_deps = new_deps.difference(old_deps)
1367
[email protected]2b438d62013-11-14 17:54:141368 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171369 for added_dep in added_deps:
1370 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1371 continue
1372 # Assume that a rule that ends in .h is a rule for a specific file.
1373 if added_dep.endswith('.h'):
1374 results.add(added_dep)
1375 else:
1376 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081377 return results
1378
1379
[email protected]e871964c2013-05-13 14:14:551380def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1381 """When a dependency prefixed with + is added to a DEPS file, we
1382 want to make sure that the change is reviewed by an OWNER of the
1383 target file or directory, to avoid layering violations from being
1384 introduced. This check verifies that this happens.
1385 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171386 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241387
1388 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191389 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241390 for f in input_api.AffectedFiles(include_deletes=False,
1391 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551392 filename = input_api.os_path.basename(f.LocalPath())
1393 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171394 virtual_depended_on_files.update(_CalculateAddedDeps(
1395 input_api.os_path,
1396 '\n'.join(f.OldContents()),
1397 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551398
[email protected]e871964c2013-05-13 14:14:551399 if not virtual_depended_on_files:
1400 return []
1401
1402 if input_api.is_committing:
1403 if input_api.tbr:
1404 return [output_api.PresubmitNotifyResult(
1405 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271406 if input_api.dry_run:
1407 return [output_api.PresubmitNotifyResult(
1408 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551409 if not input_api.change.issue:
1410 return [output_api.PresubmitError(
1411 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401412 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551413 output = output_api.PresubmitError
1414 else:
1415 output = output_api.PresubmitNotifyResult
1416
1417 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501418 owner_email, reviewers = (
1419 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1420 input_api,
1421 owners_db.email_regexp,
1422 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551423
1424 owner_email = owner_email or input_api.change.author_email
1425
[email protected]de4f7d22013-05-23 14:27:461426 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511427 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461428 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551429 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1430 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411431
1432 # We strip the /DEPS part that was added by
1433 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1434 # directory.
1435 def StripDeps(path):
1436 start_deps = path.rfind('/DEPS')
1437 if start_deps != -1:
1438 return path[:start_deps]
1439 else:
1440 return path
1441 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551442 for path in missing_files]
1443
1444 if unapproved_dependencies:
1445 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151446 output('You need LGTM from owners of depends-on paths in DEPS that were '
1447 'modified in this CL:\n %s' %
1448 '\n '.join(sorted(unapproved_dependencies)))]
1449 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1450 output_list.append(output(
1451 'Suggested missing target path OWNERS:\n %s' %
1452 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551453 return output_list
1454
1455 return []
1456
1457
[email protected]85218562013-11-22 07:41:401458def _CheckSpamLogging(input_api, output_api):
1459 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1460 black_list = (_EXCLUDED_PATHS +
1461 _TEST_CODE_EXCLUDED_PATHS +
1462 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501463 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191464 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481465 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461466 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121467 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1468 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581469 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161470 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031471 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151472 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1473 r"^chromecast[\\\/]",
1474 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481475 r"^components[\\\/]browser_watcher[\\\/]"
1476 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311477 r"^components[\\\/]html_viewer[\\\/]"
1478 r"web_test_delegate_impl\.cc$",
Samuel Huang577ef6c2018-03-13 18:19:341479 r"^components[\\\/]zucchini[\\\/].*",
peter80739bb2015-10-20 11:17:461480 # TODO(peter): Remove this exception. https://crbug.com/534537
1481 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1482 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251483 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1484 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241485 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111486 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151487 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111488 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521489 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501490 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361491 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311492 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131493 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001494 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441495 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451496 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021497 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351498 r"dump_file_system.cc$",
1499 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401500 source_file_filter = lambda x: input_api.FilterSourceFile(
1501 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1502
thomasanderson625d3932017-03-29 07:16:581503 log_info = set([])
1504 printf = set([])
[email protected]85218562013-11-22 07:41:401505
1506 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581507 for _, line in f.ChangedContents():
1508 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1509 log_info.add(f.LocalPath())
1510 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1511 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371512
thomasanderson625d3932017-03-29 07:16:581513 if input_api.re.search(r"\bprintf\(", line):
1514 printf.add(f.LocalPath())
1515 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1516 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401517
1518 if log_info:
1519 return [output_api.PresubmitError(
1520 'These files spam the console log with LOG(INFO):',
1521 items=log_info)]
1522 if printf:
1523 return [output_api.PresubmitError(
1524 'These files spam the console log with printf/fprintf:',
1525 items=printf)]
1526 return []
1527
1528
[email protected]49aa76a2013-12-04 06:59:161529def _CheckForAnonymousVariables(input_api, output_api):
1530 """These types are all expected to hold locks while in scope and
1531 so should never be anonymous (which causes them to be immediately
1532 destroyed)."""
1533 they_who_must_be_named = [
1534 'base::AutoLock',
1535 'base::AutoReset',
1536 'base::AutoUnlock',
1537 'SkAutoAlphaRestore',
1538 'SkAutoBitmapShaderInstall',
1539 'SkAutoBlitterChoose',
1540 'SkAutoBounderCommit',
1541 'SkAutoCallProc',
1542 'SkAutoCanvasRestore',
1543 'SkAutoCommentBlock',
1544 'SkAutoDescriptor',
1545 'SkAutoDisableDirectionCheck',
1546 'SkAutoDisableOvalCheck',
1547 'SkAutoFree',
1548 'SkAutoGlyphCache',
1549 'SkAutoHDC',
1550 'SkAutoLockColors',
1551 'SkAutoLockPixels',
1552 'SkAutoMalloc',
1553 'SkAutoMaskFreeImage',
1554 'SkAutoMutexAcquire',
1555 'SkAutoPathBoundsUpdate',
1556 'SkAutoPDFRelease',
1557 'SkAutoRasterClipValidate',
1558 'SkAutoRef',
1559 'SkAutoTime',
1560 'SkAutoTrace',
1561 'SkAutoUnref',
1562 ]
1563 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1564 # bad: base::AutoLock(lock.get());
1565 # not bad: base::AutoLock lock(lock.get());
1566 bad_pattern = input_api.re.compile(anonymous)
1567 # good: new base::AutoLock(lock.get())
1568 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1569 errors = []
1570
1571 for f in input_api.AffectedFiles():
1572 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1573 continue
1574 for linenum, line in f.ChangedContents():
1575 if bad_pattern.search(line) and not good_pattern.search(line):
1576 errors.append('%s:%d' % (f.LocalPath(), linenum))
1577
1578 if errors:
1579 return [output_api.PresubmitError(
1580 'These lines create anonymous variables that need to be named:',
1581 items=errors)]
1582 return []
1583
1584
Peter Kasting4844e46e2018-02-23 07:27:101585def _CheckUniquePtr(input_api, output_api):
1586 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1587 sources = lambda affected_file: input_api.FilterSourceFile(
1588 affected_file,
1589 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1590 input_api.DEFAULT_BLACK_LIST),
1591 white_list=(file_inclusion_pattern,))
Vaclav Brozeka54c528b2018-04-06 19:23:551592
1593 # Pattern to capture a single "<...>" block of template arguments. It can
1594 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
1595 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
1596 # latter would likely require counting that < and > match, which is not
1597 # expressible in regular languages. Should the need arise, one can introduce
1598 # limited counting (matching up to a total number of nesting depth), which
1599 # should cover all practical cases for already a low nesting limit.
1600 template_arg_pattern = (
1601 r'<[^>]*' # Opening block of <.
1602 r'>([^<]*>)?') # Closing block of >.
1603 # Prefix expressing that whatever follows is not already inside a <...>
1604 # block.
1605 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:101606 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:551607 not_inside_template_arg_pattern
1608 + r'\bstd::unique_ptr'
1609 + template_arg_pattern
1610 + r'\(\)')
1611
1612 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
1613 template_arg_no_array_pattern = (
1614 r'<[^>]*[^]]' # Opening block of <.
1615 r'>([^(<]*[^]]>)?') # Closing block of >.
1616 # Prefix saying that what follows is the start of an expression.
1617 start_of_expr_pattern = r'(=|\breturn|^)\s*'
1618 # Suffix saying that what follows are call parentheses with a non-empty list
1619 # of arguments.
1620 nonempty_arg_list_pattern = r'\(([^)]|$)'
1621 return_construct_pattern = input_api.re.compile(
1622 start_of_expr_pattern
1623 + r'std::unique_ptr'
1624 + template_arg_no_array_pattern
1625 + nonempty_arg_list_pattern)
1626
Vaclav Brozek851d9602018-04-04 16:13:051627 problems_constructor = []
1628 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:101629 for f in input_api.AffectedSourceFiles(sources):
1630 for line_number, line in f.ChangedContents():
1631 # Disallow:
1632 # return std::unique_ptr<T>(foo);
1633 # bar = std::unique_ptr<T>(foo);
1634 # But allow:
1635 # return std::unique_ptr<T[]>(foo);
1636 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozek851d9602018-04-04 16:13:051637 local_path = f.LocalPath()
Peter Kasting4844e46e2018-02-23 07:27:101638 if return_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:051639 problems_constructor.append(
1640 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:101641 # Disallow:
1642 # std::unique_ptr<T>()
1643 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:051644 problems_nullptr.append(
1645 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1646
1647 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:161648 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:051649 errors.append(output_api.PresubmitError(
1650 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:161651 problems_nullptr))
1652 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:051653 errors.append(output_api.PresubmitError(
1654 'The following files use explicit std::unique_ptr constructor.'
1655 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:161656 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:101657 return errors
1658
1659
[email protected]999261d2014-03-03 20:08:081660def _CheckUserActionUpdate(input_api, output_api):
1661 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521662 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081663 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521664 # If actions.xml is already included in the changelist, the PRESUBMIT
1665 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081666 return []
1667
[email protected]999261d2014-03-03 20:08:081668 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1669 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521670 current_actions = None
[email protected]999261d2014-03-03 20:08:081671 for f in input_api.AffectedFiles(file_filter=file_filter):
1672 for line_num, line in f.ChangedContents():
1673 match = input_api.re.search(action_re, line)
1674 if match:
[email protected]2f92dec2014-03-07 19:21:521675 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1676 # loaded only once.
1677 if not current_actions:
1678 with open('tools/metrics/actions/actions.xml') as actions_f:
1679 current_actions = actions_f.read()
1680 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081681 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521682 action = 'name="{0}"'.format(action_name)
1683 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081684 return [output_api.PresubmitPromptWarning(
1685 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521686 'tools/metrics/actions/actions.xml. Please run '
1687 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081688 % (f.LocalPath(), line_num, action_name))]
1689 return []
1690
1691
Daniel Cheng13ca61a882017-08-25 15:11:251692def _ImportJSONCommentEater(input_api):
1693 import sys
1694 sys.path = sys.path + [input_api.os_path.join(
1695 input_api.PresubmitLocalPath(),
1696 'tools', 'json_comment_eater')]
1697 import json_comment_eater
1698 return json_comment_eater
1699
1700
[email protected]99171a92014-06-03 08:44:471701def _GetJSONParseError(input_api, filename, eat_comments=True):
1702 try:
1703 contents = input_api.ReadFile(filename)
1704 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251705 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131706 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471707
1708 input_api.json.loads(contents)
1709 except ValueError as e:
1710 return e
1711 return None
1712
1713
1714def _GetIDLParseError(input_api, filename):
1715 try:
1716 contents = input_api.ReadFile(filename)
1717 idl_schema = input_api.os_path.join(
1718 input_api.PresubmitLocalPath(),
1719 'tools', 'json_schema_compiler', 'idl_schema.py')
1720 process = input_api.subprocess.Popen(
1721 [input_api.python_executable, idl_schema],
1722 stdin=input_api.subprocess.PIPE,
1723 stdout=input_api.subprocess.PIPE,
1724 stderr=input_api.subprocess.PIPE,
1725 universal_newlines=True)
1726 (_, error) = process.communicate(input=contents)
1727 return error or None
1728 except ValueError as e:
1729 return e
1730
1731
1732def _CheckParseErrors(input_api, output_api):
1733 """Check that IDL and JSON files do not contain syntax errors."""
1734 actions = {
1735 '.idl': _GetIDLParseError,
1736 '.json': _GetJSONParseError,
1737 }
[email protected]99171a92014-06-03 08:44:471738 # Most JSON files are preprocessed and support comments, but these do not.
1739 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491740 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471741 ]
1742 # Only run IDL checker on files in these directories.
1743 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491744 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1745 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471746 ]
1747
1748 def get_action(affected_file):
1749 filename = affected_file.LocalPath()
1750 return actions.get(input_api.os_path.splitext(filename)[1])
1751
[email protected]99171a92014-06-03 08:44:471752 def FilterFile(affected_file):
1753 action = get_action(affected_file)
1754 if not action:
1755 return False
1756 path = affected_file.LocalPath()
1757
Sean Kau46e29bc2017-08-28 16:31:161758 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471759 return False
1760
1761 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161762 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471763 return False
1764 return True
1765
1766 results = []
1767 for affected_file in input_api.AffectedFiles(
1768 file_filter=FilterFile, include_deletes=False):
1769 action = get_action(affected_file)
1770 kwargs = {}
1771 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161772 _MatchesFile(input_api, json_no_comments_patterns,
1773 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471774 kwargs['eat_comments'] = False
1775 parse_error = action(input_api,
1776 affected_file.AbsoluteLocalPath(),
1777 **kwargs)
1778 if parse_error:
1779 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1780 (affected_file.LocalPath(), parse_error)))
1781 return results
1782
1783
[email protected]760deea2013-12-10 19:33:491784def _CheckJavaStyle(input_api, output_api):
1785 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471786 import sys
[email protected]760deea2013-12-10 19:33:491787 original_sys_path = sys.path
1788 try:
1789 sys.path = sys.path + [input_api.os_path.join(
1790 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1791 import checkstyle
1792 finally:
1793 # Restore sys.path to what it was before.
1794 sys.path = original_sys_path
1795
1796 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091797 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511798 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491799
1800
Sean Kau46e29bc2017-08-28 16:31:161801def _MatchesFile(input_api, patterns, path):
1802 for pattern in patterns:
1803 if input_api.re.search(pattern, path):
1804 return True
1805 return False
1806
1807
Daniel Cheng7052cdf2017-11-21 19:23:291808def _GetOwnersFilesToCheckForIpcOwners(input_api):
1809 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:171810
Daniel Cheng7052cdf2017-11-21 19:23:291811 Returns:
1812 A dictionary mapping an OWNER file to the list of OWNERS rules it must
1813 contain to cover IPC-related files with noparent reviewer rules.
1814 """
1815 # Whether or not a file affects IPC is (mostly) determined by a simple list
1816 # of filename patterns.
dchenge07de812016-06-20 19:27:171817 file_patterns = [
palmerb19a0932017-01-24 04:00:311818 # Legacy IPC:
dchenge07de812016-06-20 19:27:171819 '*_messages.cc',
1820 '*_messages*.h',
1821 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311822 # Mojo IPC:
dchenge07de812016-06-20 19:27:171823 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:471824 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:171825 '*_struct_traits*.*',
1826 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311827 '*.typemap',
1828 # Android native IPC:
1829 '*.aidl',
1830 # Blink uses a different file naming convention:
1831 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:471832 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:171833 '*StructTraits*.*',
1834 '*TypeConverter*.*',
1835 ]
1836
scottmg7a6ed5ba2016-11-04 18:22:041837 # These third_party directories do not contain IPCs, but contain files
1838 # matching the above patterns, which trigger false positives.
1839 exclude_paths = [
1840 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291841 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041842 ]
1843
dchenge07de812016-06-20 19:27:171844 # Dictionary mapping an OWNERS file path to Patterns.
1845 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1846 # rules ) to a PatternEntry.
1847 # PatternEntry is a dictionary with two keys:
1848 # - 'files': the files that are matched by this pattern
1849 # - 'rules': the per-file rules needed for this pattern
1850 # For example, if we expect OWNERS file to contain rules for *.mojom and
1851 # *_struct_traits*.*, Patterns might look like this:
1852 # {
1853 # '*.mojom': {
1854 # 'files': ...,
1855 # 'rules': [
1856 # 'per-file *.mojom=set noparent',
1857 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1858 # ],
1859 # },
1860 # '*_struct_traits*.*': {
1861 # 'files': ...,
1862 # 'rules': [
1863 # 'per-file *_struct_traits*.*=set noparent',
1864 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1865 # ],
1866 # },
1867 # }
1868 to_check = {}
1869
Daniel Cheng13ca61a882017-08-25 15:11:251870 def AddPatternToCheck(input_file, pattern):
1871 owners_file = input_api.os_path.join(
1872 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1873 if owners_file not in to_check:
1874 to_check[owners_file] = {}
1875 if pattern not in to_check[owners_file]:
1876 to_check[owners_file][pattern] = {
1877 'files': [],
1878 'rules': [
1879 'per-file %s=set noparent' % pattern,
1880 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1881 ]
1882 }
Vaclav Brozekd5de76a2018-03-17 07:57:501883 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:251884
dchenge07de812016-06-20 19:27:171885 # Iterate through the affected files to see what we actually need to check
1886 # for. We should only nag patch authors about per-file rules if a file in that
1887 # directory would match that pattern. If a directory only contains *.mojom
1888 # files and no *_messages*.h files, we should only nag about rules for
1889 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251890 for f in input_api.AffectedFiles(include_deletes=False):
1891 # Manifest files don't have a strong naming convention. Instead, scan
1892 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161893 if (f.LocalPath().endswith('.json') and
1894 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1895 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251896 json_comment_eater = _ImportJSONCommentEater(input_api)
1897 mostly_json_lines = '\n'.join(f.NewContents())
1898 # Comments aren't allowed in strict JSON, so filter them out.
1899 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:431900 try:
1901 json_content = input_api.json.loads(json_lines)
1902 except:
1903 # There's another PRESUBMIT check that already verifies that JSON files
1904 # are not invalid, so no need to emit another warning here.
1905 continue
Daniel Cheng13ca61a882017-08-25 15:11:251906 if 'interface_provider_specs' in json_content:
1907 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171908 for pattern in file_patterns:
1909 if input_api.fnmatch.fnmatch(
1910 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041911 skip = False
1912 for exclude in exclude_paths:
1913 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1914 skip = True
1915 break
1916 if skip:
1917 continue
Daniel Cheng13ca61a882017-08-25 15:11:251918 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171919 break
1920
Daniel Cheng7052cdf2017-11-21 19:23:291921 return to_check
1922
1923
1924def _CheckIpcOwners(input_api, output_api):
1925 """Checks that affected files involving IPC have an IPC OWNERS rule."""
1926 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
1927
1928 if to_check:
1929 # If there are any OWNERS files to check, there are IPC-related changes in
1930 # this CL. Auto-CC the review list.
1931 output_api.AppendCC('[email protected]')
1932
1933 # Go through the OWNERS files to check, filtering out rules that are already
1934 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:171935 for owners_file, patterns in to_check.iteritems():
1936 try:
1937 with file(owners_file) as f:
1938 lines = set(f.read().splitlines())
1939 for entry in patterns.itervalues():
1940 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1941 ]
1942 except IOError:
1943 # No OWNERS file, so all the rules are definitely missing.
1944 continue
1945
1946 # All the remaining lines weren't found in OWNERS files, so emit an error.
1947 errors = []
1948 for owners_file, patterns in to_check.iteritems():
1949 missing_lines = []
1950 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:501951 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:171952 missing_lines.extend(entry['rules'])
1953 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1954 if missing_lines:
1955 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:051956 'Because of the presence of files:\n%s\n\n'
1957 '%s needs the following %d lines added:\n\n%s' %
1958 ('\n'.join(files), owners_file, len(missing_lines),
1959 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:171960
1961 results = []
1962 if errors:
vabrf5ce3bf92016-07-11 14:52:411963 if input_api.is_committing:
1964 output = output_api.PresubmitError
1965 else:
1966 output = output_api.PresubmitPromptWarning
1967 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591968 'Found OWNERS files that need to be updated for IPC security ' +
1969 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171970 long_text='\n\n'.join(errors)))
1971
1972 return results
1973
1974
jbriance9e12f162016-11-25 07:57:501975def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311976 """Checks that added or removed lines in non third party affected
1977 header files do not lead to new useless class or struct forward
1978 declaration.
jbriance9e12f162016-11-25 07:57:501979 """
1980 results = []
1981 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1982 input_api.re.MULTILINE)
1983 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1984 input_api.re.MULTILINE)
1985 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311986 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191987 not f.LocalPath().startswith('third_party/blink') and
1988 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311989 not f.LocalPath().startswith('third_party/WebKit') and
1990 not f.LocalPath().startswith('third_party\\WebKit')):
1991 continue
1992
jbriance9e12f162016-11-25 07:57:501993 if not f.LocalPath().endswith('.h'):
1994 continue
1995
1996 contents = input_api.ReadFile(f)
1997 fwd_decls = input_api.re.findall(class_pattern, contents)
1998 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1999
2000 useless_fwd_decls = []
2001 for decl in fwd_decls:
2002 count = sum(1 for _ in input_api.re.finditer(
2003 r'\b%s\b' % input_api.re.escape(decl), contents))
2004 if count == 1:
2005 useless_fwd_decls.append(decl)
2006
2007 if not useless_fwd_decls:
2008 continue
2009
2010 for line in f.GenerateScmDiff().splitlines():
2011 if (line.startswith('-') and not line.startswith('--') or
2012 line.startswith('+') and not line.startswith('++')):
2013 for decl in useless_fwd_decls:
2014 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
2015 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:242016 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:502017 (f.LocalPath(), decl)))
2018 useless_fwd_decls.remove(decl)
2019
2020 return results
2021
2022
dskiba88634f4e2015-08-14 23:03:292023def _CheckAndroidToastUsage(input_api, output_api):
2024 """Checks that code uses org.chromium.ui.widget.Toast instead of
2025 android.widget.Toast (Chromium Toast doesn't force hardware
2026 acceleration on low-end devices, saving memory).
2027 """
2028 toast_import_pattern = input_api.re.compile(
2029 r'^import android\.widget\.Toast;$')
2030
2031 errors = []
2032
2033 sources = lambda affected_file: input_api.FilterSourceFile(
2034 affected_file,
2035 black_list=(_EXCLUDED_PATHS +
2036 _TEST_CODE_EXCLUDED_PATHS +
2037 input_api.DEFAULT_BLACK_LIST +
2038 (r'^chromecast[\\\/].*',
2039 r'^remoting[\\\/].*')),
2040 white_list=(r'.*\.java$',))
2041
2042 for f in input_api.AffectedSourceFiles(sources):
2043 for line_num, line in f.ChangedContents():
2044 if toast_import_pattern.search(line):
2045 errors.append("%s:%d" % (f.LocalPath(), line_num))
2046
2047 results = []
2048
2049 if errors:
2050 results.append(output_api.PresubmitError(
2051 'android.widget.Toast usage is detected. Android toasts use hardware'
2052 ' acceleration, and can be\ncostly on low-end devices. Please use'
2053 ' org.chromium.ui.widget.Toast instead.\n'
2054 'Contact [email protected] if you have any questions.',
2055 errors))
2056
2057 return results
2058
2059
dgnaa68d5e2015-06-10 10:08:222060def _CheckAndroidCrLogUsage(input_api, output_api):
2061 """Checks that new logs using org.chromium.base.Log:
2062 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:512063 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:222064 """
pkotwicza1dd0b002016-05-16 14:41:042065
torne89540622017-03-24 19:41:302066 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:042067 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:302068 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:042069 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:302070 # WebView license viewer code cannot depend on //base; used in stub APK.
2071 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
2072 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:042073 ]
2074
dgnaa68d5e2015-06-10 10:08:222075 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:122076 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
2077 class_in_base_pattern = input_api.re.compile(
2078 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
2079 has_some_log_import_pattern = input_api.re.compile(
2080 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222081 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:122082 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:222083 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:512084 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:222085 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222086
Vincent Scheib16d7b272015-09-15 18:09:072087 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:222088 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:042089 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
2090 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:122091
dgnaa68d5e2015-06-10 10:08:222092 tag_decl_errors = []
2093 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:122094 tag_errors = []
dgn38736db2015-09-18 19:20:512095 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:122096 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:222097
2098 for f in input_api.AffectedSourceFiles(sources):
2099 file_content = input_api.ReadFile(f)
2100 has_modified_logs = False
2101
2102 # Per line checks
dgn87d9fb62015-06-12 09:15:122103 if (cr_log_import_pattern.search(file_content) or
2104 (class_in_base_pattern.search(file_content) and
2105 not has_some_log_import_pattern.search(file_content))):
2106 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:222107 for line_num, line in f.ChangedContents():
2108
2109 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:122110 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:222111 if match:
2112 has_modified_logs = True
2113
2114 # Make sure it uses "TAG"
2115 if not match.group('tag') == 'TAG':
2116 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:122117 else:
2118 # Report non cr Log function calls in changed lines
2119 for line_num, line in f.ChangedContents():
2120 if log_call_pattern.search(line):
2121 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:222122
2123 # Per file checks
2124 if has_modified_logs:
2125 # Make sure the tag is using the "cr" prefix and is not too long
2126 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:512127 tag_name = match.group('name') if match else None
2128 if not tag_name:
dgnaa68d5e2015-06-10 10:08:222129 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512130 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:222131 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512132 elif '.' in tag_name:
2133 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:222134
2135 results = []
2136 if tag_decl_errors:
2137 results.append(output_api.PresubmitPromptWarning(
2138 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:512139 '"private static final String TAG = "<package tag>".\n'
2140 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222141 tag_decl_errors))
2142
2143 if tag_length_errors:
2144 results.append(output_api.PresubmitError(
2145 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:512146 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222147 tag_length_errors))
2148
2149 if tag_errors:
2150 results.append(output_api.PresubmitPromptWarning(
2151 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
2152 tag_errors))
2153
dgn87d9fb62015-06-12 09:15:122154 if util_log_errors:
dgn4401aa52015-04-29 16:26:172155 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:122156 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
2157 util_log_errors))
2158
dgn38736db2015-09-18 19:20:512159 if tag_with_dot_errors:
2160 results.append(output_api.PresubmitPromptWarning(
2161 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
2162 tag_with_dot_errors))
2163
dgn4401aa52015-04-29 16:26:172164 return results
2165
2166
Yoland Yanb92fa522017-08-28 17:37:062167def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
2168 """Checks that junit.framework.* is no longer used."""
2169 deprecated_junit_framework_pattern = input_api.re.compile(
2170 r'^import junit\.framework\..*;',
2171 input_api.re.MULTILINE)
2172 sources = lambda x: input_api.FilterSourceFile(
2173 x, white_list=(r'.*\.java$',), black_list=None)
2174 errors = []
2175 for f in input_api.AffectedFiles(sources):
2176 for line_num, line in f.ChangedContents():
2177 if deprecated_junit_framework_pattern.search(line):
2178 errors.append("%s:%d" % (f.LocalPath(), line_num))
2179
2180 results = []
2181 if errors:
2182 results.append(output_api.PresubmitError(
2183 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
2184 '(org.junit.*) from //third_party/junit. Contact [email protected]'
2185 ' if you have any question.', errors))
2186 return results
2187
2188
2189def _CheckAndroidTestJUnitInheritance(input_api, output_api):
2190 """Checks that if new Java test classes have inheritance.
2191 Either the new test class is JUnit3 test or it is a JUnit4 test class
2192 with a base class, either case is undesirable.
2193 """
2194 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
2195
2196 sources = lambda x: input_api.FilterSourceFile(
2197 x, white_list=(r'.*Test\.java$',), black_list=None)
2198 errors = []
2199 for f in input_api.AffectedFiles(sources):
2200 if not f.OldContents():
2201 class_declaration_start_flag = False
2202 for line_num, line in f.ChangedContents():
2203 if class_declaration_pattern.search(line):
2204 class_declaration_start_flag = True
2205 if class_declaration_start_flag and ' extends ' in line:
2206 errors.append('%s:%d' % (f.LocalPath(), line_num))
2207 if '{' in line:
2208 class_declaration_start_flag = False
2209
2210 results = []
2211 if errors:
2212 results.append(output_api.PresubmitPromptWarning(
2213 'The newly created files include Test classes that inherits from base'
2214 ' class. Please do not use inheritance in JUnit4 tests or add new'
2215 ' JUnit3 tests. Contact [email protected] if you have any'
2216 ' questions.', errors))
2217 return results
2218
yolandyan45001472016-12-21 21:12:422219def _CheckAndroidTestAnnotationUsage(input_api, output_api):
2220 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
2221 deprecated_annotation_import_pattern = input_api.re.compile(
2222 r'^import android\.test\.suitebuilder\.annotation\..*;',
2223 input_api.re.MULTILINE)
2224 sources = lambda x: input_api.FilterSourceFile(
2225 x, white_list=(r'.*\.java$',), black_list=None)
2226 errors = []
2227 for f in input_api.AffectedFiles(sources):
2228 for line_num, line in f.ChangedContents():
2229 if deprecated_annotation_import_pattern.search(line):
2230 errors.append("%s:%d" % (f.LocalPath(), line_num))
2231
2232 results = []
2233 if errors:
2234 results.append(output_api.PresubmitError(
2235 'Annotations in android.test.suitebuilder.annotation have been'
2236 ' deprecated since API level 24. Please use android.support.test.filters'
2237 ' from //third_party/android_support_test_runner:runner_java instead.'
2238 ' Contact [email protected] if you have any questions.', errors))
2239 return results
2240
2241
agrieve7b6479d82015-10-07 14:24:222242def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
2243 """Checks if MDPI assets are placed in a correct directory."""
2244 file_filter = lambda f: (f.LocalPath().endswith('.png') and
2245 ('/res/drawable/' in f.LocalPath() or
2246 '/res/drawable-ldrtl/' in f.LocalPath()))
2247 errors = []
2248 for f in input_api.AffectedFiles(include_deletes=False,
2249 file_filter=file_filter):
2250 errors.append(' %s' % f.LocalPath())
2251
2252 results = []
2253 if errors:
2254 results.append(output_api.PresubmitError(
2255 'MDPI assets should be placed in /res/drawable-mdpi/ or '
2256 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
2257 '/res/drawable-ldrtl/.\n'
2258 'Contact [email protected] if you have questions.', errors))
2259 return results
2260
2261
Nate Fischer535972b2017-09-16 01:06:182262def _CheckAndroidWebkitImports(input_api, output_api):
2263 """Checks that code uses org.chromium.base.Callback instead of
2264 android.widget.ValueCallback except in the WebView glue layer.
2265 """
2266 valuecallback_import_pattern = input_api.re.compile(
2267 r'^import android\.webkit\.ValueCallback;$')
2268
2269 errors = []
2270
2271 sources = lambda affected_file: input_api.FilterSourceFile(
2272 affected_file,
2273 black_list=(_EXCLUDED_PATHS +
2274 _TEST_CODE_EXCLUDED_PATHS +
2275 input_api.DEFAULT_BLACK_LIST +
2276 (r'^android_webview[\\\/]glue[\\\/].*',)),
2277 white_list=(r'.*\.java$',))
2278
2279 for f in input_api.AffectedSourceFiles(sources):
2280 for line_num, line in f.ChangedContents():
2281 if valuecallback_import_pattern.search(line):
2282 errors.append("%s:%d" % (f.LocalPath(), line_num))
2283
2284 results = []
2285
2286 if errors:
2287 results.append(output_api.PresubmitError(
2288 'android.webkit.ValueCallback usage is detected outside of the glue'
2289 ' layer. To stay compatible with the support library, android.webkit.*'
2290 ' classes should only be used inside the glue layer and'
2291 ' org.chromium.base.Callback should be used instead.',
2292 errors))
2293
2294 return results
2295
2296
agrievef32bcc72016-04-04 14:57:402297class PydepsChecker(object):
2298 def __init__(self, input_api, pydeps_files):
2299 self._file_cache = {}
2300 self._input_api = input_api
2301 self._pydeps_files = pydeps_files
2302
2303 def _LoadFile(self, path):
2304 """Returns the list of paths within a .pydeps file relative to //."""
2305 if path not in self._file_cache:
2306 with open(path) as f:
2307 self._file_cache[path] = f.read()
2308 return self._file_cache[path]
2309
2310 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
2311 """Returns an interable of paths within the .pydep, relativized to //."""
2312 os_path = self._input_api.os_path
2313 pydeps_dir = os_path.dirname(pydeps_path)
2314 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2315 if not l.startswith('*'))
2316 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2317
2318 def _CreateFilesToPydepsMap(self):
2319 """Returns a map of local_path -> list_of_pydeps."""
2320 ret = {}
2321 for pydep_local_path in self._pydeps_files:
2322 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2323 ret.setdefault(path, []).append(pydep_local_path)
2324 return ret
2325
2326 def ComputeAffectedPydeps(self):
2327 """Returns an iterable of .pydeps files that might need regenerating."""
2328 affected_pydeps = set()
2329 file_to_pydeps_map = None
2330 for f in self._input_api.AffectedFiles(include_deletes=True):
2331 local_path = f.LocalPath()
2332 if local_path == 'DEPS':
2333 return self._pydeps_files
2334 elif local_path.endswith('.pydeps'):
2335 if local_path in self._pydeps_files:
2336 affected_pydeps.add(local_path)
2337 elif local_path.endswith('.py'):
2338 if file_to_pydeps_map is None:
2339 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2340 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2341 return affected_pydeps
2342
2343 def DetermineIfStale(self, pydeps_path):
2344 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412345 import difflib
John Budorick47ca3fe2018-02-10 00:53:102346 import os
2347
agrievef32bcc72016-04-04 14:57:402348 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2349 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:102350 env = dict(os.environ)
2351 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:402352 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:102353 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412354 old_contents = old_pydeps_data[2:]
2355 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402356 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412357 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402358
2359
2360def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2361 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:402362 # This check is for Python dependency lists (.pydeps files), and involves
2363 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
2364 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:282365 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002366 return []
Mostyn Bramley-Moore6b427322017-12-21 22:11:022367 # TODO(agrieve): Update when there's a better way to detect
2368 # this: crbug.com/570091
agrievef32bcc72016-04-04 14:57:402369 is_android = input_api.os_path.exists('third_party/android_tools')
2370 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2371 results = []
2372 # First, check for new / deleted .pydeps.
2373 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:032374 # Check whether we are running the presubmit check for a file in src.
2375 # f.LocalPath is relative to repo (src, or internal repo).
2376 # os_path.exists is relative to src repo.
2377 # Therefore if os_path.exists is true, it means f.LocalPath is relative
2378 # to src and we can conclude that the pydeps is in src.
2379 if input_api.os_path.exists(f.LocalPath()):
2380 if f.LocalPath().endswith('.pydeps'):
2381 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2382 results.append(output_api.PresubmitError(
2383 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2384 'remove %s' % f.LocalPath()))
2385 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2386 results.append(output_api.PresubmitError(
2387 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2388 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:402389
2390 if results:
2391 return results
2392
2393 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2394
2395 for pydep_path in checker.ComputeAffectedPydeps():
2396 try:
phajdan.jr0d9878552016-11-04 10:49:412397 result = checker.DetermineIfStale(pydep_path)
2398 if result:
2399 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402400 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412401 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2402 'To regenerate, run:\n\n %s' %
2403 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402404 except input_api.subprocess.CalledProcessError as error:
2405 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2406 long_text=error.output)]
2407
2408 return results
2409
2410
glidere61efad2015-02-18 17:39:432411def _CheckSingletonInHeaders(input_api, output_api):
2412 """Checks to make sure no header files have |Singleton<|."""
2413 def FileFilter(affected_file):
2414 # It's ok for base/memory/singleton.h to have |Singleton<|.
2415 black_list = (_EXCLUDED_PATHS +
2416 input_api.DEFAULT_BLACK_LIST +
Michael Warrese4451492018-03-07 04:42:472417 (r"^base[\\\/]memory[\\\/]singleton\.h$",
2418 r"^net[\\\/]quic[\\\/]platform[\\\/]impl[\\\/]"
2419 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:432420 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2421
sergeyu34d21222015-09-16 00:11:442422 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432423 files = []
2424 for f in input_api.AffectedSourceFiles(FileFilter):
2425 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2426 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2427 contents = input_api.ReadFile(f)
2428 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242429 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432430 pattern.search(line)):
2431 files.append(f)
2432 break
2433
2434 if files:
yolandyandaabc6d2016-04-18 18:29:392435 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442436 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432437 'Please move them to an appropriate source file so that the ' +
2438 'template gets instantiated in a single compilation unit.',
2439 files) ]
2440 return []
2441
2442
[email protected]fd20b902014-05-09 02:14:532443_DEPRECATED_CSS = [
2444 # Values
2445 ( "-webkit-box", "flex" ),
2446 ( "-webkit-inline-box", "inline-flex" ),
2447 ( "-webkit-flex", "flex" ),
2448 ( "-webkit-inline-flex", "inline-flex" ),
2449 ( "-webkit-min-content", "min-content" ),
2450 ( "-webkit-max-content", "max-content" ),
2451
2452 # Properties
2453 ( "-webkit-background-clip", "background-clip" ),
2454 ( "-webkit-background-origin", "background-origin" ),
2455 ( "-webkit-background-size", "background-size" ),
2456 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442457 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532458
2459 # Functions
2460 ( "-webkit-gradient", "gradient" ),
2461 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2462 ( "-webkit-linear-gradient", "linear-gradient" ),
2463 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2464 ( "-webkit-radial-gradient", "radial-gradient" ),
2465 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2466]
2467
dbeam1ec68ac2016-12-15 05:22:242468def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532469 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252470 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342471 documentation and iOS CSS for dom distiller
2472 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252473 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532474 results = []
dbeam070cfe62014-10-22 06:44:022475 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252476 black_list = (_EXCLUDED_PATHS +
2477 _TEST_CODE_EXCLUDED_PATHS +
2478 input_api.DEFAULT_BLACK_LIST +
2479 (r"^chrome/common/extensions/docs",
2480 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342481 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442482 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252483 r"^native_client_sdk"))
2484 file_filter = lambda f: input_api.FilterSourceFile(
2485 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532486 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2487 for line_num, line in fpath.ChangedContents():
2488 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022489 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532490 results.append(output_api.PresubmitError(
2491 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2492 (fpath.LocalPath(), line_num, deprecated_value, value)))
2493 return results
2494
mohan.reddyf21db962014-10-16 12:26:472495
dbeam070cfe62014-10-22 06:44:022496_DEPRECATED_JS = [
2497 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2498 ( "__defineGetter__", "Object.defineProperty" ),
2499 ( "__defineSetter__", "Object.defineProperty" ),
2500]
2501
dbeam1ec68ac2016-12-15 05:22:242502def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022503 """Make sure that we don't use deprecated JS in Chrome code."""
2504 results = []
2505 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2506 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2507 input_api.DEFAULT_BLACK_LIST)
2508 file_filter = lambda f: input_api.FilterSourceFile(
2509 f, white_list=file_inclusion_pattern, black_list=black_list)
2510 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2511 for lnum, line in fpath.ChangedContents():
2512 for (deprecated, replacement) in _DEPRECATED_JS:
2513 if deprecated in line:
2514 results.append(output_api.PresubmitError(
2515 "%s:%d: Use of deprecated JS %s, use %s instead" %
2516 (fpath.LocalPath(), lnum, deprecated, replacement)))
2517 return results
2518
dpapadd651231d82017-07-21 02:44:472519def _CheckForRiskyJsArrowFunction(line_number, line):
2520 if ' => ' in line:
2521 return "line %d, is using an => (arrow) function\n %s\n" % (
2522 line_number, line)
2523 return ''
2524
2525def _CheckForRiskyJsConstLet(input_api, line_number, line):
2526 if input_api.re.match('^\s*(const|let)\s', line):
2527 return "line %d, is using const/let keyword\n %s\n" % (
2528 line_number, line)
2529 return ''
dbeam070cfe62014-10-22 06:44:022530
dbeam1ec68ac2016-12-15 05:22:242531def _CheckForRiskyJsFeatures(input_api, output_api):
2532 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002533 # 'ui/webui/resources/cr_components are not allowed on ios'
2534 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572535 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002536 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472537 results = []
dbeam1ec68ac2016-12-15 05:22:242538 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472539 arrow_error_lines = []
2540 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242541 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472542 arrow_error_lines += filter(None, [
2543 _CheckForRiskyJsArrowFunction(lnum, line),
2544 ])
dbeam1ec68ac2016-12-15 05:22:242545
dpapadd651231d82017-07-21 02:44:472546 const_let_error_lines += filter(None, [
2547 _CheckForRiskyJsConstLet(input_api, lnum, line),
2548 ])
dbeam1ec68ac2016-12-15 05:22:242549
dpapadd651231d82017-07-21 02:44:472550 if arrow_error_lines:
2551 arrow_error_lines = map(
2552 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2553 results.append(
2554 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2555"""
2556Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242557%s
2558Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2559https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472560""" % f.LocalPath()
2561 ])))
dbeam1ec68ac2016-12-15 05:22:242562
dpapadd651231d82017-07-21 02:44:472563 if const_let_error_lines:
2564 const_let_error_lines = map(
2565 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2566 results.append(
2567 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2568"""
2569Use of const/let keywords detected in:
2570%s
2571Please ensure your code does not run on iOS9 because const/let is not fully
2572supported.
2573https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2574https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2575""" % f.LocalPath()
2576 ])))
2577
2578 return results
dbeam1ec68ac2016-12-15 05:22:242579
rlanday6802cf632017-05-30 17:48:362580def _CheckForRelativeIncludes(input_api, output_api):
2581 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2582 import sys
2583 original_sys_path = sys.path
2584 try:
2585 sys.path = sys.path + [input_api.os_path.join(
2586 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2587 from cpp_checker import CppChecker
2588 finally:
2589 # Restore sys.path to what it was before.
2590 sys.path = original_sys_path
2591
2592 bad_files = {}
2593 for f in input_api.AffectedFiles(include_deletes=False):
2594 if (f.LocalPath().startswith('third_party') and
2595 not f.LocalPath().startswith('third_party/WebKit') and
2596 not f.LocalPath().startswith('third_party\\WebKit')):
2597 continue
2598
2599 if not CppChecker.IsCppFile(f.LocalPath()):
2600 continue
2601
Vaclav Brozekd5de76a2018-03-17 07:57:502602 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:362603 if "#include" in line and "../" in line]
2604 if not relative_includes:
2605 continue
2606 bad_files[f.LocalPath()] = relative_includes
2607
2608 if not bad_files:
2609 return []
2610
2611 error_descriptions = []
2612 for file_path, bad_lines in bad_files.iteritems():
2613 error_description = file_path
2614 for line in bad_lines:
2615 error_description += '\n ' + line
2616 error_descriptions.append(error_description)
2617
2618 results = []
2619 results.append(output_api.PresubmitError(
2620 'You added one or more relative #include paths (including "../").\n'
2621 'These shouldn\'t be used because they can be used to include headers\n'
2622 'from code that\'s not correctly specified as a dependency in the\n'
2623 'relevant BUILD.gn file(s).',
2624 error_descriptions))
2625
2626 return results
2627
Takeshi Yoshinoe387aa32017-08-02 13:16:132628
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202629def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2630 if not isinstance(key, ast.Str):
2631 return 'Key at line %d must be a string literal' % key.lineno
2632 if not isinstance(value, ast.Dict):
2633 return 'Value at line %d must be a dict' % value.lineno
2634 if len(value.keys) != 1:
2635 return 'Dict at line %d must have single entry' % value.lineno
2636 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2637 return (
2638 'Entry at line %d must have a string literal \'filepath\' as key' %
2639 value.lineno)
2640 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132641
Takeshi Yoshinoe387aa32017-08-02 13:16:132642
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202643def _CheckWatchlistsEntrySyntax(key, value, ast):
2644 if not isinstance(key, ast.Str):
2645 return 'Key at line %d must be a string literal' % key.lineno
2646 if not isinstance(value, ast.List):
2647 return 'Value at line %d must be a list' % value.lineno
2648 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132649
Takeshi Yoshinoe387aa32017-08-02 13:16:132650
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202651def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2652 mismatch_template = (
2653 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2654 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132655
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202656 i = 0
2657 last_key = ''
2658 while True:
2659 if i >= len(wd_dict.keys):
2660 if i >= len(w_dict.keys):
2661 return None
2662 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2663 elif i >= len(w_dict.keys):
2664 return (
2665 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132666
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202667 wd_key = wd_dict.keys[i]
2668 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132669
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202670 result = _CheckWatchlistDefinitionsEntrySyntax(
2671 wd_key, wd_dict.values[i], ast)
2672 if result is not None:
2673 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132674
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202675 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2676 if result is not None:
2677 return 'Bad entry in WATCHLISTS dict: %s' % result
2678
2679 if wd_key.s != w_key.s:
2680 return mismatch_template % (
2681 '%s at line %d' % (wd_key.s, wd_key.lineno),
2682 '%s at line %d' % (w_key.s, w_key.lineno))
2683
2684 if wd_key.s < last_key:
2685 return (
2686 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2687 (wd_key.lineno, w_key.lineno))
2688 last_key = wd_key.s
2689
2690 i = i + 1
2691
2692
2693def _CheckWATCHLISTSSyntax(expression, ast):
2694 if not isinstance(expression, ast.Expression):
2695 return 'WATCHLISTS file must contain a valid expression'
2696 dictionary = expression.body
2697 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2698 return 'WATCHLISTS file must have single dict with exactly two entries'
2699
2700 first_key = dictionary.keys[0]
2701 first_value = dictionary.values[0]
2702 second_key = dictionary.keys[1]
2703 second_value = dictionary.values[1]
2704
2705 if (not isinstance(first_key, ast.Str) or
2706 first_key.s != 'WATCHLIST_DEFINITIONS' or
2707 not isinstance(first_value, ast.Dict)):
2708 return (
2709 'The first entry of the dict in WATCHLISTS file must be '
2710 'WATCHLIST_DEFINITIONS dict')
2711
2712 if (not isinstance(second_key, ast.Str) or
2713 second_key.s != 'WATCHLISTS' or
2714 not isinstance(second_value, ast.Dict)):
2715 return (
2716 'The second entry of the dict in WATCHLISTS file must be '
2717 'WATCHLISTS dict')
2718
2719 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132720
2721
2722def _CheckWATCHLISTS(input_api, output_api):
2723 for f in input_api.AffectedFiles(include_deletes=False):
2724 if f.LocalPath() == 'WATCHLISTS':
2725 contents = input_api.ReadFile(f, 'r')
2726
2727 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202728 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132729 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202730 # Get an AST tree for it and scan the tree for detailed style checking.
2731 expression = input_api.ast.parse(
2732 contents, filename='WATCHLISTS', mode='eval')
2733 except ValueError as e:
2734 return [output_api.PresubmitError(
2735 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2736 except SyntaxError as e:
2737 return [output_api.PresubmitError(
2738 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2739 except TypeError as e:
2740 return [output_api.PresubmitError(
2741 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132742
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202743 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2744 if result is not None:
2745 return [output_api.PresubmitError(result)]
2746 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132747
2748 return []
2749
2750
dgnaa68d5e2015-06-10 10:08:222751def _AndroidSpecificOnUploadChecks(input_api, output_api):
2752 """Groups checks that target android code."""
2753 results = []
dgnaa68d5e2015-06-10 10:08:222754 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222755 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292756 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062757 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2758 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422759 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182760 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222761 return results
2762
2763
[email protected]22c9bd72011-03-27 16:47:392764def _CommonChecks(input_api, output_api):
2765 """Checks common to both upload and commit."""
2766 results = []
2767 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382768 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542769 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:082770
2771 author = input_api.change.author_email
2772 if author and author not in _KNOWN_ROBOTS:
2773 results.extend(
2774 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
2775
[email protected]55459852011-08-10 15:17:192776 results.extend(
[email protected]760deea2013-12-10 19:33:492777 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:232778 results.extend(
2779 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542780 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182781 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522782 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222783 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442784 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592785 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062786 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122787 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182788 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222789 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302790 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492791 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032792 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492793 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442794 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272795 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072796 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542797 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442798 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392799 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552800 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042801 results.extend(
2802 input_api.canned_checks.CheckChangeHasNoTabs(
2803 input_api,
2804 output_api,
2805 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402806 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162807 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082808 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242809 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2810 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472811 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042812 results.extend(_CheckForIPCRules(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:142813 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232814 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432815 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402816 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152817 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172818 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502819 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242820 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362821 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132822 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432823 results.extend(input_api.RunTests(
2824 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242825
Vaclav Brozekcdc7defb2018-03-20 09:54:352826 for f in input_api.AffectedFiles():
2827 path, name = input_api.os_path.split(f.LocalPath())
2828 if name == 'PRESUBMIT.py':
2829 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Dirk Pranke38557312018-04-18 00:53:072830 if f.Action() != 'D':
2831 # The PRESUBMIT.py file (and the directory containing it) might
2832 # have been affected by being moved or removed, so only try to
2833 # run the tests if they still exist.
2834 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2835 input_api, output_api, full_path,
2836 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392837 return results
[email protected]1f7b4172010-01-28 01:17:342838
[email protected]b337cb5b2011-01-23 21:24:052839
[email protected]b8079ae4a2012-12-05 19:56:492840def _CheckPatchFiles(input_api, output_api):
2841 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2842 if f.LocalPath().endswith(('.orig', '.rej'))]
2843 if problems:
2844 return [output_api.PresubmitError(
2845 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032846 else:
2847 return []
[email protected]b8079ae4a2012-12-05 19:56:492848
2849
Kent Tamura5a8755d2017-06-29 23:37:072850def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212851 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2852 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2853 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072854 include_re = input_api.re.compile(
2855 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2856 extension_re = input_api.re.compile(r'\.[a-z]+$')
2857 errors = []
2858 for f in input_api.AffectedFiles():
2859 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2860 continue
2861 found_line_number = None
2862 found_macro = None
2863 for line_num, line in f.ChangedContents():
2864 match = macro_re.search(line)
2865 if match:
2866 found_line_number = line_num
2867 found_macro = match.group(2)
2868 break
2869 if not found_line_number:
2870 continue
2871
2872 found_include = False
2873 for line in f.NewContents():
2874 if include_re.search(line):
2875 found_include = True
2876 break
2877 if found_include:
2878 continue
2879
2880 if not f.LocalPath().endswith('.h'):
2881 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2882 try:
2883 content = input_api.ReadFile(primary_header_path, 'r')
2884 if include_re.search(content):
2885 continue
2886 except IOError:
2887 pass
2888 errors.append('%s:%d %s macro is used without including build/'
2889 'build_config.h.'
2890 % (f.LocalPath(), found_line_number, found_macro))
2891 if errors:
2892 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2893 return []
2894
2895
[email protected]b00342e7f2013-03-26 16:21:542896def _DidYouMeanOSMacro(bad_macro):
2897 try:
2898 return {'A': 'OS_ANDROID',
2899 'B': 'OS_BSD',
2900 'C': 'OS_CHROMEOS',
2901 'F': 'OS_FREEBSD',
2902 'L': 'OS_LINUX',
2903 'M': 'OS_MACOSX',
2904 'N': 'OS_NACL',
2905 'O': 'OS_OPENBSD',
2906 'P': 'OS_POSIX',
2907 'S': 'OS_SOLARIS',
2908 'W': 'OS_WIN'}[bad_macro[3].upper()]
2909 except KeyError:
2910 return ''
2911
2912
2913def _CheckForInvalidOSMacrosInFile(input_api, f):
2914 """Check for sensible looking, totally invalid OS macros."""
2915 preprocessor_statement = input_api.re.compile(r'^\s*#')
2916 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2917 results = []
2918 for lnum, line in f.ChangedContents():
2919 if preprocessor_statement.search(line):
2920 for match in os_macro.finditer(line):
2921 if not match.group(1) in _VALID_OS_MACROS:
2922 good = _DidYouMeanOSMacro(match.group(1))
2923 did_you_mean = ' (did you mean %s?)' % good if good else ''
2924 results.append(' %s:%d %s%s' % (f.LocalPath(),
2925 lnum,
2926 match.group(1),
2927 did_you_mean))
2928 return results
2929
2930
2931def _CheckForInvalidOSMacros(input_api, output_api):
2932 """Check all affected files for invalid OS macros."""
2933 bad_macros = []
2934 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472935 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542936 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2937
2938 if not bad_macros:
2939 return []
2940
2941 return [output_api.PresubmitError(
2942 'Possibly invalid OS macro[s] found. Please fix your code\n'
2943 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2944
lliabraa35bab3932014-10-01 12:16:442945
2946def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2947 """Check all affected files for invalid "if defined" macros."""
2948 ALWAYS_DEFINED_MACROS = (
2949 "TARGET_CPU_PPC",
2950 "TARGET_CPU_PPC64",
2951 "TARGET_CPU_68K",
2952 "TARGET_CPU_X86",
2953 "TARGET_CPU_ARM",
2954 "TARGET_CPU_MIPS",
2955 "TARGET_CPU_SPARC",
2956 "TARGET_CPU_ALPHA",
2957 "TARGET_IPHONE_SIMULATOR",
2958 "TARGET_OS_EMBEDDED",
2959 "TARGET_OS_IPHONE",
2960 "TARGET_OS_MAC",
2961 "TARGET_OS_UNIX",
2962 "TARGET_OS_WIN32",
2963 )
2964 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2965 results = []
2966 for lnum, line in f.ChangedContents():
2967 for match in ifdef_macro.finditer(line):
2968 if match.group(1) in ALWAYS_DEFINED_MACROS:
2969 always_defined = ' %s is always defined. ' % match.group(1)
2970 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2971 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2972 lnum,
2973 always_defined,
2974 did_you_mean))
2975 return results
2976
2977
2978def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2979 """Check all affected files for invalid "if defined" macros."""
2980 bad_macros = []
2981 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212982 if f.LocalPath().startswith('third_party/sqlite/'):
2983 continue
lliabraa35bab3932014-10-01 12:16:442984 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2985 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2986
2987 if not bad_macros:
2988 return []
2989
2990 return [output_api.PresubmitError(
2991 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2992 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2993 bad_macros)]
2994
2995
mlamouria82272622014-09-16 18:45:042996def _CheckForIPCRules(input_api, output_api):
2997 """Check for same IPC rules described in
2998 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2999 """
3000 base_pattern = r'IPC_ENUM_TRAITS\('
3001 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
3002 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
3003
3004 problems = []
3005 for f in input_api.AffectedSourceFiles(None):
3006 local_path = f.LocalPath()
3007 if not local_path.endswith('.h'):
3008 continue
3009 for line_number, line in f.ChangedContents():
3010 if inclusion_pattern.search(line) and not comment_pattern.search(line):
3011 problems.append(
3012 '%s:%d\n %s' % (local_path, line_number, line.strip()))
3013
3014 if problems:
3015 return [output_api.PresubmitPromptWarning(
3016 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
3017 else:
3018 return []
3019
[email protected]b00342e7f2013-03-26 16:21:543020
Daniel Bratell8ba52722018-03-02 16:06:143021def _CheckForIncludeGuards(input_api, output_api):
3022 """Check that header files have proper guards against multiple inclusion.
3023 If a file should not have such guards (and it probably should) then it
3024 should include the string "no-include-guard-because-multiply-included".
3025 """
3026 def is_header_file(f):
3027 return f.LocalPath().endswith('.h')
3028
3029 def replace_special_with_underscore(string):
3030 return input_api.re.sub(r'[\\/.-]', '_', string)
3031
3032 errors = []
3033
3034 for f in input_api.AffectedSourceFiles(is_header_file):
3035 guard_name = None
3036 guard_line_number = None
3037 seen_guard_end = False
3038
3039 file_with_path = input_api.os_path.normpath(f.LocalPath())
3040 base_file_name = input_api.os_path.splitext(
3041 input_api.os_path.basename(file_with_path))[0]
3042 upper_base_file_name = base_file_name.upper()
3043
3044 expected_guard = replace_special_with_underscore(
3045 file_with_path.upper() + '_')
3046 expected_guard_if_blink = base_file_name + '_h'
3047
3048 # For "path/elem/file_name.h" we should really only accept
3049 # PATH_ELEM_FILE_NAME_H_ per coding style or, if Blink,
3050 # file_name_h. Unfortunately there are too many (1000+) files
3051 # with slight deviations from the coding style. Since the most
3052 # important part is that the include guard is there, and that it's
3053 # unique, not the name, this check is forgiving for existing files.
3054 #
3055 # As code becomes more uniform, this could be made stricter.
3056
3057 guard_name_pattern_list = [
3058 # Anything with the right suffix (maybe with an extra _).
3059 r'\w+_H__?',
3060
3061 # To cover include guards with Blink style.
3062 r'\w+_h',
3063
3064 # Anything including the uppercase name of the file.
3065 r'\w*' + input_api.re.escape(replace_special_with_underscore(
3066 upper_base_file_name)) + r'\w*',
3067 ]
3068 guard_name_pattern = '|'.join(guard_name_pattern_list)
3069 guard_pattern = input_api.re.compile(
3070 r'#ifndef\s+(' + guard_name_pattern + ')')
3071
3072 for line_number, line in enumerate(f.NewContents()):
3073 if 'no-include-guard-because-multiply-included' in line:
3074 guard_name = 'DUMMY' # To not trigger check outside the loop.
3075 break
3076
3077 if guard_name is None:
3078 match = guard_pattern.match(line)
3079 if match:
3080 guard_name = match.group(1)
3081 guard_line_number = line_number
3082
3083 # We allow existing files to use slightly wrong include
3084 # guards, but new files should get it right.
3085 if not f.OldContents():
3086 is_in_blink = file_with_path.startswith(input_api.os_path.join(
3087 'third_party', 'WebKit'))
3088 if not (guard_name == expected_guard or
3089 is_in_blink and guard_name == expected_guard_if_blink):
3090 if is_in_blink:
3091 expected_text = "%s or %s" % (expected_guard,
3092 expected_guard_if_blink)
3093 else:
3094 expected_text = expected_guard
3095 errors.append(output_api.PresubmitPromptWarning(
3096 'Header using the wrong include guard name %s' % guard_name,
3097 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Daniel Bratell00e1b9bc2018-03-12 13:11:123098 'Expected: %r\nFound: %r' % (expected_text, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:143099 else:
3100 # The line after #ifndef should have a #define of the same name.
3101 if line_number == guard_line_number + 1:
3102 expected_line = '#define %s' % guard_name
3103 if line != expected_line:
3104 errors.append(output_api.PresubmitPromptWarning(
3105 'Missing "%s" for include guard' % expected_line,
3106 ['%s:%d' % (f.LocalPath(), line_number + 1)],
3107 'Expected: %r\nGot: %r' % (expected_line, line)))
3108
3109 if not seen_guard_end and line == '#endif // %s' % guard_name:
3110 seen_guard_end = True
3111 elif seen_guard_end:
3112 if line.strip() != '':
3113 errors.append(output_api.PresubmitPromptWarning(
3114 'Include guard %s not covering the whole file' % (
3115 guard_name), [f.LocalPath()]))
3116 break # Nothing else to check and enough to warn once.
3117
3118 if guard_name is None:
3119 errors.append(output_api.PresubmitPromptWarning(
3120 'Missing include guard %s' % expected_guard,
3121 [f.LocalPath()],
3122 'Missing include guard in %s\n'
3123 'Recommended name: %s\n'
3124 'This check can be disabled by having the string\n'
3125 'no-include-guard-because-multiply-included in the header.' %
3126 (f.LocalPath(), expected_guard)))
3127
3128 return errors
3129
3130
mostynbb639aca52015-01-07 20:31:233131def _CheckForWindowsLineEndings(input_api, output_api):
3132 """Check source code and known ascii text files for Windows style line
3133 endings.
3134 """
earthdok1b5e0ee2015-03-10 15:19:103135 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:233136
3137 file_inclusion_pattern = (
3138 known_text_files,
3139 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3140 )
3141
mostynbb639aca52015-01-07 20:31:233142 problems = []
Andrew Grieve933d12e2017-10-30 20:22:533143 source_file_filter = lambda f: input_api.FilterSourceFile(
3144 f, white_list=file_inclusion_pattern, black_list=None)
3145 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:503146 include_file = False
3147 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:233148 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:503149 include_file = True
3150 if include_file:
3151 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:233152
3153 if problems:
3154 return [output_api.PresubmitPromptWarning('Are you sure that you want '
3155 'these files to contain Windows style line endings?\n' +
3156 '\n'.join(problems))]
3157
3158 return []
3159
3160
Vaclav Brozekd5de76a2018-03-17 07:57:503161def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:133162 """Checks that all source files use SYSLOG properly."""
3163 syslog_files = []
3164 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:563165 for line_number, line in f.ChangedContents():
3166 if 'SYSLOG' in line:
3167 syslog_files.append(f.LocalPath() + ':' + str(line_number))
3168
pastarmovj89f7ee12016-09-20 14:58:133169 if syslog_files:
3170 return [output_api.PresubmitPromptWarning(
3171 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
3172 ' calls.\nFiles to check:\n', items=syslog_files)]
3173 return []
3174
3175
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193176def _CheckCrbugLinksHaveHttps(input_api, output_api):
Miguel Casas68bdb652017-12-19 16:29:093177 """Checks that crbug(.com) links are correctly prefixed by https://,
3178 unless they come in the accepted form TODO(crbug.com/...)
3179 """
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193180 white_list = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3181 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS)
3182 sources = lambda f: input_api.FilterSourceFile(
3183 f, white_list=white_list, black_list=black_list)
3184
3185 pattern = input_api.re.compile(r'//.*(?<!:\/\/)crbug[.com]*')
Miguel Casas68bdb652017-12-19 16:29:093186 accepted_pattern = input_api.re.compile(r'//.*TODO\(crbug[.com]*');
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193187 problems = []
3188 for f in input_api.AffectedSourceFiles(sources):
3189 for line_num, line in f.ChangedContents():
Miguel Casas68bdb652017-12-19 16:29:093190 if pattern.search(line) and not accepted_pattern.search(line):
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193191 problems.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
3192
3193 if problems:
3194 return [output_api.PresubmitPromptWarning(
3195 'Found unprefixed crbug.com URL(s), consider prepending https://\n'+
3196 '\n'.join(problems))]
3197 return []
3198
3199
[email protected]1f7b4172010-01-28 01:17:343200def CheckChangeOnUpload(input_api, output_api):
3201 results = []
3202 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:473203 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:283204 results.extend(
jam93a6ee792017-02-08 23:59:223205 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:193206 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:223207 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:133208 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:163209 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193210 results.extend(_CheckCrbugLinksHaveHttps(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:533211 results.extend(_CheckUniquePtr(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543212 return results
[email protected]ca8d1982009-02-19 16:33:123213
3214
[email protected]1bfb8322014-04-23 01:02:413215def GetTryServerMasterForBot(bot):
3216 """Returns the Try Server master for the given bot.
3217
[email protected]0bb112362014-07-26 04:38:323218 It tries to guess the master from the bot name, but may still fail
3219 and return None. There is no longer a default master.
3220 """
3221 # Potentially ambiguous bot names are listed explicitly.
3222 master_map = {
tandriie5587792016-07-14 00:34:503223 'chromium_presubmit': 'master.tryserver.chromium.linux',
3224 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:413225 }
[email protected]0bb112362014-07-26 04:38:323226 master = master_map.get(bot)
3227 if not master:
wnwen4fbaab82016-05-25 12:54:363228 if 'android' in bot:
tandriie5587792016-07-14 00:34:503229 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:363230 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:503231 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:323232 elif 'win' in bot:
tandriie5587792016-07-14 00:34:503233 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:323234 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:503235 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:323236 return master
[email protected]1bfb8322014-04-23 01:02:413237
3238
[email protected]ca8d1982009-02-19 16:33:123239def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:543240 results = []
[email protected]1f7b4172010-01-28 01:17:343241 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543242 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:273243 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:343244 input_api,
3245 output_api,
[email protected]2fdd1f362013-01-16 03:56:033246 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:273247
jam93a6ee792017-02-08 23:59:223248 results.extend(
3249 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:543250 results.extend(input_api.canned_checks.CheckChangeHasBugField(
3251 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:413252 results.extend(input_api.canned_checks.CheckChangeHasDescription(
3253 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543254 return results