blob: ad5dfe79ae03b3b4b0a19a54b546c55c62b8a7ab [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',
405 'third_party/leveldatabase/leveldb_chrome.h.',
406 ),
407 True,
408 (
409 r'^third_party/leveldatabase/.*\.(cc|h)$',
410 ),
411 ),
412 (
Gabriel Charetted9839bc2017-07-29 14:17:47413 'MessageLoop::QuitWhenIdleClosure',
Gabriel Charette0592c3a2017-07-26 12:02:04414 (
Peter Kasting9e7ccfa52018-02-06 00:01:20415 'MessageLoop::QuitWhenIdleClosure is deprecated. Please use a',
416 'QuitWhenIdleClosure obtained from a specific RunLoop instance.',
Gabriel Charette0592c3a2017-07-26 12:02:04417 ),
Peter Kasting9e7ccfa52018-02-06 00:01:20418 False,
Gabriel Charette0592c3a2017-07-26 12:02:04419 (),
Gabriel Charetted9839bc2017-07-29 14:17:47420 ),
421 (
422 'RunLoop::QuitCurrent',
423 (
Robert Liao64b7ab22017-08-04 23:03:43424 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
425 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47426 ),
427 True,
428 (),
Gabriel Charettea44975052017-08-21 23:14:04429 ),
430 (
431 'base::ScopedMockTimeMessageLoopTaskRunner',
432 (
433 'ScopedMockTimeMessageLoopTaskRunner is deprecated.',
434 ),
435 True,
436 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57437 ),
438 (
439 r'std::regex',
440 (
441 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02442 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57443 ),
444 True,
445 (),
Francois Doray43670e32017-09-27 12:40:38446 ),
447 (
448 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
449 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
450 (
451 'Use the new API in base/threading/thread_restrictions.h.',
452 ),
453 True,
454 (),
455 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38456 (
457 r'/\bbase::Bind\(',
458 (
Gabriel Charette147335ea2018-03-22 15:59:19459 'Please consider using base::Bind{Once,Repeating} instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02460 'of base::Bind. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38461 ),
462 False,
463 (),
464 ),
465 (
466 r'/\bbase::Callback<',
467 (
Gabriel Charette147335ea2018-03-22 15:59:19468 'Please consider using base::{Once,Repeating}Callback instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02469 'of base::Callback. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38470 ),
471 False,
472 (),
473 ),
474 (
475 r'/\bbase::Closure\b',
476 (
Gabriel Charette147335ea2018-03-22 15:59:19477 'Please consider using base::{Once,Repeating}Closure instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02478 'of base::Closure. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38479 ),
480 False,
481 (),
482 ),
Victor Costan3653df62018-02-08 21:38:16483 (
Gabriel Charette147335ea2018-03-22 15:59:19484 r'RunMessageLoop',
485 (
486 'RunMessageLoop is deprecated, use RunLoop instead.',
487 ),
488 False,
489 (),
490 ),
491 (
492 r'RunThisRunLoop',
493 (
494 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
495 ),
496 False,
497 (),
498 ),
499 (
500 r'RunAllPendingInMessageLoop()',
501 (
502 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
503 "if you're convinced you need this.",
504 ),
505 False,
506 (),
507 ),
508 (
509 r'RunAllPendingInMessageLoop(BrowserThread',
510 (
511 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
512 'BrowserThread::UI, TestBrowserThreadBundle::RunIOThreadUntilIdle',
513 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
514 'async events instead of flushing threads.',
515 ),
516 False,
517 (),
518 ),
519 (
520 r'MessageLoopRunner',
521 (
522 'MessageLoopRunner is deprecated, use RunLoop instead.',
523 ),
524 False,
525 (),
526 ),
527 (
528 r'GetDeferredQuitTaskForRunLoop',
529 (
530 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
531 "gab@ if you found a use case where this is the only solution.",
532 ),
533 False,
534 (),
535 ),
536 (
Victor Costan3653df62018-02-08 21:38:16537 'sqlite3_initialize',
538 (
539 'Instead of sqlite3_initialize, depend on //sql, ',
540 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
541 ),
542 True,
543 (
544 r'^sql/initialization\.(cc|h)$',
545 r'^third_party/sqlite/.*\.(c|cc|h)$',
546 ),
547 ),
Matt Menke7f520a82018-03-28 21:38:37548 (
549 'net::URLFetcher',
550 (
551 'net::URLFetcher should no longer be used in content embedders. ',
552 'Instead, use network::SimpleURLLoader instead, which supports ',
553 'an out-of-process network stack. ',
554 'net::URLFetcher may still be used in binaries that do not embed',
555 'content.',
556 ),
Matt Menke59716d02018-04-05 12:45:53557 False,
Matt Menke7f520a82018-03-28 21:38:37558 (
559 r'^ios[\\\/].*\.(cc|h)$',
560 r'.*[\\\/]ios[\\\/].*\.(cc|h)$',
561 r'.*_ios\.(cc|h)$',
562 r'^net[\\\/].*\.(cc|h)$',
563 r'.*[\\\/]tools[\\\/].*\.(cc|h)$',
564 ),
565 ),
[email protected]127f18ec2012-06-16 05:05:59566)
567
wnwenbdc444e2016-05-25 13:44:15568
mlamouria82272622014-09-16 18:45:04569_IPC_ENUM_TRAITS_DEPRECATED = (
570 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50571 'See http://www.chromium.org/Home/chromium-security/education/'
572 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:04573
Shenghua Zhangbfaa38b82017-11-16 21:58:02574_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
575 r".*[\\\/]BuildHooksAndroidImpl\.java",
576 r".*[\\\/]LicenseContentProvider\.java",
577]
[email protected]127f18ec2012-06-16 05:05:59578
Sean Kau46e29bc2017-08-28 16:31:16579# These paths contain test data and other known invalid JSON files.
580_KNOWN_INVALID_JSON_FILE_PATTERNS = [
581 r'test[\\\/]data[\\\/]',
582 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
583 r'^third_party[\\\/]protobuf[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16584 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Alexey Kozyatinskiya42a629f2018-04-17 17:49:38585 r'^third_party[\\\/]blink[\\\/]renderer[\\\/]devtools[\\\/]protocol\.json$',
Sean Kau46e29bc2017-08-28 16:31:16586]
587
588
[email protected]b00342e7f2013-03-26 16:21:54589_VALID_OS_MACROS = (
590 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08591 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54592 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:12593 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:54594 'OS_BSD',
595 'OS_CAT', # For testing.
596 'OS_CHROMEOS',
597 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37598 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54599 'OS_IOS',
600 'OS_LINUX',
601 'OS_MACOSX',
602 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21603 'OS_NACL_NONSFI',
604 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12605 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54606 'OS_OPENBSD',
607 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37608 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54609 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54610 'OS_WIN',
611)
612
613
agrievef32bcc72016-04-04 14:57:40614_ANDROID_SPECIFIC_PYDEPS_FILES = [
615 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04616 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58617 'build/secondary/third_party/android_platform/'
618 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19619 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40620]
621
wnwenbdc444e2016-05-25 13:44:15622
agrievef32bcc72016-04-04 14:57:40623_GENERIC_PYDEPS_FILES = [
John Chencde89192018-01-27 21:18:40624 'chrome/test/chromedriver/test/run_py_tests.pydeps',
agrievef32bcc72016-04-04 14:57:40625]
626
wnwenbdc444e2016-05-25 13:44:15627
agrievef32bcc72016-04-04 14:57:40628_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
629
630
Eric Boren6fd2b932018-01-25 15:05:08631# Bypass the AUTHORS check for these accounts.
632_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:29633 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
634 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
635 'fuchsia-sdk', 'nacl', 'pdfium', 'skia', 'src-internal', 'webrtc')
636 ) | set('%[email protected]' % s for s in ('findit-for-me',))
Eric Boren6fd2b932018-01-25 15:05:08637
638
[email protected]55459852011-08-10 15:17:19639def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
640 """Attempts to prevent use of functions intended only for testing in
641 non-testing code. For now this is just a best-effort implementation
642 that ignores header files and may have some false positives. A
643 better implementation would probably need a proper C++ parser.
644 """
645 # We only scan .cc files and the like, as the declaration of
646 # for-testing functions in header files are hard to distinguish from
647 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44648 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19649
jochenc0d4808c2015-07-27 09:25:42650 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19651 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09652 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19653 exclusion_pattern = input_api.re.compile(
654 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
655 base_function_pattern, base_function_pattern))
656
657 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44658 black_list = (_EXCLUDED_PATHS +
659 _TEST_CODE_EXCLUDED_PATHS +
660 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19661 return input_api.FilterSourceFile(
662 affected_file,
663 white_list=(file_inclusion_pattern, ),
664 black_list=black_list)
665
666 problems = []
667 for f in input_api.AffectedSourceFiles(FilterFile):
668 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24669 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03670 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46671 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03672 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19673 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03674 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19675
676 if problems:
[email protected]f7051d52013-04-02 18:31:42677 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03678 else:
679 return []
[email protected]55459852011-08-10 15:17:19680
681
Vaclav Brozek7dbc28c2018-03-27 08:35:23682def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
683 """This is a simplified version of
684 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
685 """
686 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
687 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
688 name_pattern = r'ForTest(s|ing)?'
689 # Describes an occurrence of "ForTest*" inside a // comment.
690 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
691 # Catch calls.
692 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
693 # Ignore definitions. (Comments are ignored separately.)
694 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
695
696 problems = []
697 sources = lambda x: input_api.FilterSourceFile(
698 x,
699 black_list=(('(?i).*test', r'.*\/junit\/')
700 + input_api.DEFAULT_BLACK_LIST),
701 white_list=(r'.*\.java$',)
702 )
703 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
704 local_path = f.LocalPath()
705 is_inside_javadoc = False
706 for line_number, line in f.ChangedContents():
707 if is_inside_javadoc and javadoc_end_re.search(line):
708 is_inside_javadoc = False
709 if not is_inside_javadoc and javadoc_start_re.search(line):
710 is_inside_javadoc = True
711 if is_inside_javadoc:
712 continue
713 if (inclusion_re.search(line) and
714 not comment_re.search(line) and
715 not exclusion_re.search(line)):
716 problems.append(
717 '%s:%d\n %s' % (local_path, line_number, line.strip()))
718
719 if problems:
720 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
721 else:
722 return []
723
724
[email protected]10689ca2011-09-02 02:31:54725def _CheckNoIOStreamInHeaders(input_api, output_api):
726 """Checks to make sure no .h files include <iostream>."""
727 files = []
728 pattern = input_api.re.compile(r'^#include\s*<iostream>',
729 input_api.re.MULTILINE)
730 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
731 if not f.LocalPath().endswith('.h'):
732 continue
733 contents = input_api.ReadFile(f)
734 if pattern.search(contents):
735 files.append(f)
736
737 if len(files):
yolandyandaabc6d2016-04-18 18:29:39738 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06739 'Do not #include <iostream> in header files, since it inserts static '
740 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54741 '#include <ostream>. See http://crbug.com/94794',
742 files) ]
743 return []
744
745
[email protected]72df4e782012-06-21 16:28:18746def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52747 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18748 problems = []
749 for f in input_api.AffectedFiles():
750 if (not f.LocalPath().endswith(('.cc', '.mm'))):
751 continue
752
753 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04754 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18755 problems.append(' %s:%d' % (f.LocalPath(), line_num))
756
757 if not problems:
758 return []
759 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
760 '\n'.join(problems))]
761
762
danakj61c1aa22015-10-26 19:55:52763def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57764 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52765 errors = []
766 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
767 input_api.re.MULTILINE)
768 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
769 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
770 continue
771 for lnum, line in f.ChangedContents():
772 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17773 errors.append(output_api.PresubmitError(
774 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57775 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17776 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52777 return errors
778
779
mcasasb7440c282015-02-04 14:52:19780def _FindHistogramNameInLine(histogram_name, line):
781 """Tries to find a histogram name or prefix in a line."""
782 if not "affected-histogram" in line:
783 return histogram_name in line
784 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
785 # the histogram_name.
786 if not '"' in line:
787 return False
788 histogram_prefix = line.split('\"')[1]
789 return histogram_prefix in histogram_name
790
791
792def _CheckUmaHistogramChanges(input_api, output_api):
793 """Check that UMA histogram names in touched lines can still be found in other
794 lines of the patch or in histograms.xml. Note that this check would not catch
795 the reverse: changes in histograms.xml not matched in the code itself."""
796 touched_histograms = []
797 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:47798 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
799 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
800 name_pattern = r'"(.*?)"'
801 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
802 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
803 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
804 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
805 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:17806 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:19807 for f in input_api.AffectedFiles():
808 # If histograms.xml itself is modified, keep the modified lines for later.
809 if f.LocalPath().endswith(('histograms.xml')):
810 histograms_xml_modifications = f.ChangedContents()
811 continue
Vaclav Brozekbdac817c2018-03-24 06:30:47812 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
813 single_line_re = single_line_c_re
814 split_line_prefix_re = split_line_c_prefix_re
815 elif f.LocalPath().endswith(('java')):
816 single_line_re = single_line_java_re
817 split_line_prefix_re = split_line_java_prefix_re
818 else:
mcasasb7440c282015-02-04 14:52:19819 continue
820 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:17821 if last_line_matched_prefix:
822 suffix_found = split_line_suffix_re.search(line)
823 if suffix_found :
824 touched_histograms.append([suffix_found.group(1), f, line_num])
825 last_line_matched_prefix = False
826 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:06827 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:19828 if found:
829 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:17830 continue
831 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:19832
833 # Search for the touched histogram names in the local modifications to
834 # histograms.xml, and, if not found, on the base histograms.xml file.
835 unmatched_histograms = []
836 for histogram_info in touched_histograms:
837 histogram_name_found = False
838 for line_num, line in histograms_xml_modifications:
839 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
840 if histogram_name_found:
841 break
842 if not histogram_name_found:
843 unmatched_histograms.append(histogram_info)
844
eromanb90c82e7e32015-04-01 15:13:49845 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19846 problems = []
847 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49848 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19849 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45850 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19851 histogram_name_found = False
852 for line in histograms_xml:
853 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
854 if histogram_name_found:
855 break
856 if not histogram_name_found:
857 problems.append(' [%s:%d] %s' %
858 (f.LocalPath(), line_num, histogram_name))
859
860 if not problems:
861 return []
862 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
863 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49864 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19865
wnwenbdc444e2016-05-25 13:44:15866
yolandyandaabc6d2016-04-18 18:29:39867def _CheckFlakyTestUsage(input_api, output_api):
868 """Check that FlakyTest annotation is our own instead of the android one"""
869 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
870 files = []
871 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
872 if f.LocalPath().endswith('Test.java'):
873 if pattern.search(input_api.ReadFile(f)):
874 files.append(f)
875 if len(files):
876 return [output_api.PresubmitError(
877 'Use org.chromium.base.test.util.FlakyTest instead of '
878 'android.test.FlakyTest',
879 files)]
880 return []
mcasasb7440c282015-02-04 14:52:19881
wnwenbdc444e2016-05-25 13:44:15882
[email protected]8ea5d4b2011-09-13 21:49:22883def _CheckNoNewWStrings(input_api, output_api):
884 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27885 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22886 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20887 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57888 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34889 '/win/' in f.LocalPath() or
890 'chrome_elf' in f.LocalPath() or
891 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20892 continue
[email protected]8ea5d4b2011-09-13 21:49:22893
[email protected]a11dbe9b2012-08-07 01:32:58894 allowWString = False
[email protected]b5c24292011-11-28 14:38:20895 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58896 if 'presubmit: allow wstring' in line:
897 allowWString = True
898 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27899 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58900 allowWString = False
901 else:
902 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22903
[email protected]55463aa62011-10-12 00:48:27904 if not problems:
905 return []
906 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58907 ' If you are calling a cross-platform API that accepts a wstring, '
908 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27909 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22910
911
[email protected]2a8ac9c2011-10-19 17:20:44912def _CheckNoDEPSGIT(input_api, output_api):
913 """Make sure .DEPS.git is never modified manually."""
914 if any(f.LocalPath().endswith('.DEPS.git') for f in
915 input_api.AffectedFiles()):
916 return [output_api.PresubmitError(
917 'Never commit changes to .DEPS.git. This file is maintained by an\n'
918 'automated system based on what\'s in DEPS and your changes will be\n'
919 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50920 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
921 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:44922 'for more information')]
923 return []
924
925
tandriief664692014-09-23 14:51:47926def _CheckValidHostsInDEPS(input_api, output_api):
927 """Checks that DEPS file deps are from allowed_hosts."""
928 # Run only if DEPS file has been modified to annoy fewer bystanders.
929 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
930 return []
931 # Outsource work to gclient verify
932 try:
933 input_api.subprocess.check_output(['gclient', 'verify'])
934 return []
935 except input_api.subprocess.CalledProcessError, error:
936 return [output_api.PresubmitError(
937 'DEPS file must have only git dependencies.',
938 long_text=error.output)]
939
940
[email protected]127f18ec2012-06-16 05:05:59941def _CheckNoBannedFunctions(input_api, output_api):
942 """Make sure that banned functions are not used."""
943 warnings = []
944 errors = []
945
wnwenbdc444e2016-05-25 13:44:15946 def IsBlacklisted(affected_file, blacklist):
947 local_path = affected_file.LocalPath()
948 for item in blacklist:
949 if input_api.re.match(item, local_path):
950 return True
951 return False
952
Sylvain Defresnea8b73d252018-02-28 15:45:54953 def IsIosObcjFile(affected_file):
954 local_path = affected_file.LocalPath()
955 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
956 return False
957 basename = input_api.os_path.basename(local_path)
958 if 'ios' in basename.split('_'):
959 return True
960 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
961 if sep and 'ios' in local_path.split(sep):
962 return True
963 return False
964
wnwenbdc444e2016-05-25 13:44:15965 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
966 matched = False
967 if func_name[0:1] == '/':
968 regex = func_name[1:]
969 if input_api.re.search(regex, line):
970 matched = True
971 elif func_name in line:
dchenge07de812016-06-20 19:27:17972 matched = True
wnwenbdc444e2016-05-25 13:44:15973 if matched:
dchenge07de812016-06-20 19:27:17974 problems = warnings
wnwenbdc444e2016-05-25 13:44:15975 if error:
dchenge07de812016-06-20 19:27:17976 problems = errors
wnwenbdc444e2016-05-25 13:44:15977 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
978 for message_line in message:
979 problems.append(' %s' % message_line)
980
Eric Stevensona9a980972017-09-23 00:04:41981 file_filter = lambda f: f.LocalPath().endswith(('.java'))
982 for f in input_api.AffectedFiles(file_filter=file_filter):
983 for line_num, line in f.ChangedContents():
984 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
985 CheckForMatch(f, line_num, line, func_name, message, error)
986
[email protected]127f18ec2012-06-16 05:05:59987 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
988 for f in input_api.AffectedFiles(file_filter=file_filter):
989 for line_num, line in f.ChangedContents():
990 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15991 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59992
Sylvain Defresnea8b73d252018-02-28 15:45:54993 for f in input_api.AffectedFiles(file_filter=IsIosObcjFile):
994 for line_num, line in f.ChangedContents():
995 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
996 CheckForMatch(f, line_num, line, func_name, message, error)
997
[email protected]127f18ec2012-06-16 05:05:59998 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
999 for f in input_api.AffectedFiles(file_filter=file_filter):
1000 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491001 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491002 if IsBlacklisted(f, excluded_paths):
1003 continue
wnwenbdc444e2016-05-25 13:44:151004 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591005
1006 result = []
1007 if (warnings):
1008 result.append(output_api.PresubmitPromptWarning(
1009 'Banned functions were used.\n' + '\n'.join(warnings)))
1010 if (errors):
1011 result.append(output_api.PresubmitError(
1012 'Banned functions were used.\n' + '\n'.join(errors)))
1013 return result
1014
1015
[email protected]6c063c62012-07-11 19:11:061016def _CheckNoPragmaOnce(input_api, output_api):
1017 """Make sure that banned functions are not used."""
1018 files = []
1019 pattern = input_api.re.compile(r'^#pragma\s+once',
1020 input_api.re.MULTILINE)
1021 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1022 if not f.LocalPath().endswith('.h'):
1023 continue
1024 contents = input_api.ReadFile(f)
1025 if pattern.search(contents):
1026 files.append(f)
1027
1028 if files:
1029 return [output_api.PresubmitError(
1030 'Do not use #pragma once in header files.\n'
1031 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1032 files)]
1033 return []
1034
[email protected]127f18ec2012-06-16 05:05:591035
[email protected]e7479052012-09-19 00:26:121036def _CheckNoTrinaryTrueFalse(input_api, output_api):
1037 """Checks to make sure we don't introduce use of foo ? true : false."""
1038 problems = []
1039 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1040 for f in input_api.AffectedFiles():
1041 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1042 continue
1043
1044 for line_num, line in f.ChangedContents():
1045 if pattern.match(line):
1046 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1047
1048 if not problems:
1049 return []
1050 return [output_api.PresubmitPromptWarning(
1051 'Please consider avoiding the "? true : false" pattern if possible.\n' +
1052 '\n'.join(problems))]
1053
1054
[email protected]55f9f382012-07-31 11:02:181055def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:281056 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:181057 change. Breaking - rules is an error, breaking ! rules is a
1058 warning.
1059 """
mohan.reddyf21db962014-10-16 12:26:471060 import sys
[email protected]55f9f382012-07-31 11:02:181061 # We need to wait until we have an input_api object and use this
1062 # roundabout construct to import checkdeps because this file is
1063 # eval-ed and thus doesn't have __file__.
1064 original_sys_path = sys.path
1065 try:
1066 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:471067 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:181068 import checkdeps
1069 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:241070 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:281071 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:181072 from rules import Rule
1073 finally:
1074 # Restore sys.path to what it was before.
1075 sys.path = original_sys_path
1076
1077 added_includes = []
rhalavati08acd232017-04-03 07:23:281078 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:241079 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:181080 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:281081 if CppChecker.IsCppFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501082 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081083 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:281084 elif ProtoChecker.IsProtoFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501085 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081086 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:241087 elif JavaChecker.IsJavaFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501088 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081089 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:181090
[email protected]26385172013-05-09 23:11:351091 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181092
1093 error_descriptions = []
1094 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:281095 error_subjects = set()
1096 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:181097 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
1098 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:081099 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181100 description_with_path = '%s\n %s' % (path, rule_description)
1101 if rule_type == Rule.DISALLOW:
1102 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281103 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:181104 else:
1105 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281106 warning_subjects.add("#includes")
1107
1108 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
1109 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:081110 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:281111 description_with_path = '%s\n %s' % (path, rule_description)
1112 if rule_type == Rule.DISALLOW:
1113 error_descriptions.append(description_with_path)
1114 error_subjects.add("imports")
1115 else:
1116 warning_descriptions.append(description_with_path)
1117 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:181118
Jinsuk Kim5a092672017-10-24 22:42:241119 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:021120 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:081121 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:241122 description_with_path = '%s\n %s' % (path, rule_description)
1123 if rule_type == Rule.DISALLOW:
1124 error_descriptions.append(description_with_path)
1125 error_subjects.add("imports")
1126 else:
1127 warning_descriptions.append(description_with_path)
1128 warning_subjects.add("imports")
1129
[email protected]55f9f382012-07-31 11:02:181130 results = []
1131 if error_descriptions:
1132 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:281133 'You added one or more %s that violate checkdeps rules.'
1134 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:181135 error_descriptions))
1136 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:421137 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:281138 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:181139 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:281140 '%s? See relevant DEPS file(s) for details and contacts.' %
1141 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:181142 warning_descriptions))
1143 return results
1144
1145
[email protected]fbcafe5a2012-08-08 15:31:221146def _CheckFilePermissions(input_api, output_api):
1147 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:151148 if input_api.platform == 'win32':
1149 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:291150 checkperms_tool = input_api.os_path.join(
1151 input_api.PresubmitLocalPath(),
1152 'tools', 'checkperms', 'checkperms.py')
1153 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:471154 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:391155 with input_api.CreateTemporaryFile() as file_list:
1156 for f in input_api.AffectedFiles():
1157 # checkperms.py file/directory arguments must be relative to the
1158 # repository.
1159 file_list.write(f.LocalPath() + '\n')
1160 file_list.close()
1161 args += ['--file-list', file_list.name]
1162 try:
1163 input_api.subprocess.check_output(args)
1164 return []
1165 except input_api.subprocess.CalledProcessError as error:
1166 return [output_api.PresubmitError(
1167 'checkperms.py failed:',
1168 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:221169
1170
robertocn832f5992017-01-04 19:01:301171def _CheckTeamTags(input_api, output_api):
1172 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
1173 checkteamtags_tool = input_api.os_path.join(
1174 input_api.PresubmitLocalPath(),
1175 'tools', 'checkteamtags', 'checkteamtags.py')
1176 args = [input_api.python_executable, checkteamtags_tool,
1177 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:221178 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:301179 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
1180 'OWNERS']
1181 try:
1182 if files:
1183 input_api.subprocess.check_output(args + files)
1184 return []
1185 except input_api.subprocess.CalledProcessError as error:
1186 return [output_api.PresubmitError(
1187 'checkteamtags.py failed:',
1188 long_text=error.output)]
1189
1190
[email protected]c8278b32012-10-30 20:35:491191def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
1192 """Makes sure we don't include ui/aura/window_property.h
1193 in header files.
1194 """
1195 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1196 errors = []
1197 for f in input_api.AffectedFiles():
1198 if not f.LocalPath().endswith('.h'):
1199 continue
1200 for line_num, line in f.ChangedContents():
1201 if pattern.match(line):
1202 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1203
1204 results = []
1205 if errors:
1206 results.append(output_api.PresubmitError(
1207 'Header files should not include ui/aura/window_property.h', errors))
1208 return results
1209
1210
[email protected]70ca77752012-11-20 03:45:031211def _CheckForVersionControlConflictsInFile(input_api, f):
1212 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1213 errors = []
1214 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231215 if f.LocalPath().endswith('.md'):
1216 # First-level headers in markdown look a lot like version control
1217 # conflict markers. http://daringfireball.net/projects/markdown/basics
1218 continue
[email protected]70ca77752012-11-20 03:45:031219 if pattern.match(line):
1220 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1221 return errors
1222
1223
1224def _CheckForVersionControlConflicts(input_api, output_api):
1225 """Usually this is not intentional and will cause a compile failure."""
1226 errors = []
1227 for f in input_api.AffectedFiles():
1228 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1229
1230 results = []
1231 if errors:
1232 results.append(output_api.PresubmitError(
1233 'Version control conflict markers found, please resolve.', errors))
1234 return results
1235
estadee17314a02017-01-12 16:22:161236def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1237 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1238 errors = []
1239 for f in input_api.AffectedFiles():
1240 for line_num, line in f.ChangedContents():
1241 if pattern.search(line):
1242 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1243
1244 results = []
1245 if errors:
1246 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:501247 'Found Google support URL addressed by answer number. Please replace '
1248 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:161249 return results
1250
[email protected]70ca77752012-11-20 03:45:031251
[email protected]06e6d0ff2012-12-11 01:36:441252def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1253 def FilterFile(affected_file):
1254 """Filter function for use with input_api.AffectedSourceFiles,
1255 below. This filters out everything except non-test files from
1256 top-level directories that generally speaking should not hard-code
1257 service URLs (e.g. src/android_webview/, src/content/ and others).
1258 """
1259 return input_api.FilterSourceFile(
1260 affected_file,
[email protected]78bb39d62012-12-11 15:11:561261 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441262 black_list=(_EXCLUDED_PATHS +
1263 _TEST_CODE_EXCLUDED_PATHS +
1264 input_api.DEFAULT_BLACK_LIST))
1265
reillyi38965732015-11-16 18:27:331266 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1267 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461268 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1269 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441270 problems = [] # items are (filename, line_number, line)
1271 for f in input_api.AffectedSourceFiles(FilterFile):
1272 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461273 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441274 problems.append((f.LocalPath(), line_num, line))
1275
1276 if problems:
[email protected]f7051d52013-04-02 18:31:421277 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441278 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581279 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441280 [' %s:%d: %s' % (
1281 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031282 else:
1283 return []
[email protected]06e6d0ff2012-12-11 01:36:441284
1285
[email protected]d2530012013-01-25 16:39:271286def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1287 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311288 The native_client_sdk directory is excluded because it has auto-generated PNG
1289 files for documentation.
[email protected]d2530012013-01-25 16:39:271290 """
[email protected]d2530012013-01-25 16:39:271291 errors = []
binji0dcdf342014-12-12 18:32:311292 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1293 black_list = (r'^native_client_sdk[\\\/]',)
1294 file_filter = lambda f: input_api.FilterSourceFile(
1295 f, white_list=white_list, black_list=black_list)
1296 for f in input_api.AffectedFiles(include_deletes=False,
1297 file_filter=file_filter):
1298 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271299
1300 results = []
1301 if errors:
1302 results.append(output_api.PresubmitError(
1303 'The name of PNG files should not have abbreviations. \n'
1304 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1305 'Contact [email protected] if you have questions.', errors))
1306 return results
1307
1308
Daniel Cheng4dcdb6b2017-04-13 08:30:171309def _ExtractAddRulesFromParsedDeps(parsed_deps):
1310 """Extract the rules that add dependencies from a parsed DEPS file.
1311
1312 Args:
1313 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1314 add_rules = set()
1315 add_rules.update([
1316 rule[1:] for rule in parsed_deps.get('include_rules', [])
1317 if rule.startswith('+') or rule.startswith('!')
1318 ])
Vaclav Brozekd5de76a2018-03-17 07:57:501319 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:171320 {}).iteritems():
1321 add_rules.update([
1322 rule[1:] for rule in rules
1323 if rule.startswith('+') or rule.startswith('!')
1324 ])
1325 return add_rules
1326
1327
1328def _ParseDeps(contents):
1329 """Simple helper for parsing DEPS files."""
1330 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171331 class _VarImpl:
1332
1333 def __init__(self, local_scope):
1334 self._local_scope = local_scope
1335
1336 def Lookup(self, var_name):
1337 """Implements the Var syntax."""
1338 try:
1339 return self._local_scope['vars'][var_name]
1340 except KeyError:
1341 raise Exception('Var is not defined: %s' % var_name)
1342
1343 local_scope = {}
1344 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171345 'Var': _VarImpl(local_scope).Lookup,
1346 }
1347 exec contents in global_scope, local_scope
1348 return local_scope
1349
1350
1351def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081352 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411353 a set of DEPS entries that we should look up.
1354
1355 For a directory (rather than a specific filename) we fake a path to
1356 a specific filename by adding /DEPS. This is chosen as a file that
1357 will seldom or never be subject to per-file include_rules.
1358 """
[email protected]2b438d62013-11-14 17:54:141359 # We ignore deps entries on auto-generated directories.
1360 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081361
Daniel Cheng4dcdb6b2017-04-13 08:30:171362 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1363 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1364
1365 added_deps = new_deps.difference(old_deps)
1366
[email protected]2b438d62013-11-14 17:54:141367 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171368 for added_dep in added_deps:
1369 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1370 continue
1371 # Assume that a rule that ends in .h is a rule for a specific file.
1372 if added_dep.endswith('.h'):
1373 results.add(added_dep)
1374 else:
1375 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081376 return results
1377
1378
[email protected]e871964c2013-05-13 14:14:551379def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1380 """When a dependency prefixed with + is added to a DEPS file, we
1381 want to make sure that the change is reviewed by an OWNER of the
1382 target file or directory, to avoid layering violations from being
1383 introduced. This check verifies that this happens.
1384 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171385 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241386
1387 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191388 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241389 for f in input_api.AffectedFiles(include_deletes=False,
1390 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551391 filename = input_api.os_path.basename(f.LocalPath())
1392 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171393 virtual_depended_on_files.update(_CalculateAddedDeps(
1394 input_api.os_path,
1395 '\n'.join(f.OldContents()),
1396 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551397
[email protected]e871964c2013-05-13 14:14:551398 if not virtual_depended_on_files:
1399 return []
1400
1401 if input_api.is_committing:
1402 if input_api.tbr:
1403 return [output_api.PresubmitNotifyResult(
1404 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271405 if input_api.dry_run:
1406 return [output_api.PresubmitNotifyResult(
1407 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551408 if not input_api.change.issue:
1409 return [output_api.PresubmitError(
1410 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401411 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551412 output = output_api.PresubmitError
1413 else:
1414 output = output_api.PresubmitNotifyResult
1415
1416 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501417 owner_email, reviewers = (
1418 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1419 input_api,
1420 owners_db.email_regexp,
1421 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551422
1423 owner_email = owner_email or input_api.change.author_email
1424
[email protected]de4f7d22013-05-23 14:27:461425 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511426 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461427 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551428 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1429 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411430
1431 # We strip the /DEPS part that was added by
1432 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1433 # directory.
1434 def StripDeps(path):
1435 start_deps = path.rfind('/DEPS')
1436 if start_deps != -1:
1437 return path[:start_deps]
1438 else:
1439 return path
1440 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551441 for path in missing_files]
1442
1443 if unapproved_dependencies:
1444 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151445 output('You need LGTM from owners of depends-on paths in DEPS that were '
1446 'modified in this CL:\n %s' %
1447 '\n '.join(sorted(unapproved_dependencies)))]
1448 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1449 output_list.append(output(
1450 'Suggested missing target path OWNERS:\n %s' %
1451 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551452 return output_list
1453
1454 return []
1455
1456
[email protected]85218562013-11-22 07:41:401457def _CheckSpamLogging(input_api, output_api):
1458 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1459 black_list = (_EXCLUDED_PATHS +
1460 _TEST_CODE_EXCLUDED_PATHS +
1461 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501462 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191463 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481464 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461465 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121466 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1467 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581468 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161469 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031470 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151471 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1472 r"^chromecast[\\\/]",
1473 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481474 r"^components[\\\/]browser_watcher[\\\/]"
1475 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311476 r"^components[\\\/]html_viewer[\\\/]"
1477 r"web_test_delegate_impl\.cc$",
Samuel Huang577ef6c2018-03-13 18:19:341478 r"^components[\\\/]zucchini[\\\/].*",
peter80739bb2015-10-20 11:17:461479 # TODO(peter): Remove this exception. https://crbug.com/534537
1480 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1481 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251482 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1483 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241484 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111485 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151486 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111487 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521488 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501489 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361490 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311491 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131492 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001493 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441494 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451495 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021496 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351497 r"dump_file_system.cc$",
1498 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401499 source_file_filter = lambda x: input_api.FilterSourceFile(
1500 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1501
thomasanderson625d3932017-03-29 07:16:581502 log_info = set([])
1503 printf = set([])
[email protected]85218562013-11-22 07:41:401504
1505 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581506 for _, line in f.ChangedContents():
1507 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1508 log_info.add(f.LocalPath())
1509 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1510 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371511
thomasanderson625d3932017-03-29 07:16:581512 if input_api.re.search(r"\bprintf\(", line):
1513 printf.add(f.LocalPath())
1514 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1515 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401516
1517 if log_info:
1518 return [output_api.PresubmitError(
1519 'These files spam the console log with LOG(INFO):',
1520 items=log_info)]
1521 if printf:
1522 return [output_api.PresubmitError(
1523 'These files spam the console log with printf/fprintf:',
1524 items=printf)]
1525 return []
1526
1527
[email protected]49aa76a2013-12-04 06:59:161528def _CheckForAnonymousVariables(input_api, output_api):
1529 """These types are all expected to hold locks while in scope and
1530 so should never be anonymous (which causes them to be immediately
1531 destroyed)."""
1532 they_who_must_be_named = [
1533 'base::AutoLock',
1534 'base::AutoReset',
1535 'base::AutoUnlock',
1536 'SkAutoAlphaRestore',
1537 'SkAutoBitmapShaderInstall',
1538 'SkAutoBlitterChoose',
1539 'SkAutoBounderCommit',
1540 'SkAutoCallProc',
1541 'SkAutoCanvasRestore',
1542 'SkAutoCommentBlock',
1543 'SkAutoDescriptor',
1544 'SkAutoDisableDirectionCheck',
1545 'SkAutoDisableOvalCheck',
1546 'SkAutoFree',
1547 'SkAutoGlyphCache',
1548 'SkAutoHDC',
1549 'SkAutoLockColors',
1550 'SkAutoLockPixels',
1551 'SkAutoMalloc',
1552 'SkAutoMaskFreeImage',
1553 'SkAutoMutexAcquire',
1554 'SkAutoPathBoundsUpdate',
1555 'SkAutoPDFRelease',
1556 'SkAutoRasterClipValidate',
1557 'SkAutoRef',
1558 'SkAutoTime',
1559 'SkAutoTrace',
1560 'SkAutoUnref',
1561 ]
1562 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1563 # bad: base::AutoLock(lock.get());
1564 # not bad: base::AutoLock lock(lock.get());
1565 bad_pattern = input_api.re.compile(anonymous)
1566 # good: new base::AutoLock(lock.get())
1567 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1568 errors = []
1569
1570 for f in input_api.AffectedFiles():
1571 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1572 continue
1573 for linenum, line in f.ChangedContents():
1574 if bad_pattern.search(line) and not good_pattern.search(line):
1575 errors.append('%s:%d' % (f.LocalPath(), linenum))
1576
1577 if errors:
1578 return [output_api.PresubmitError(
1579 'These lines create anonymous variables that need to be named:',
1580 items=errors)]
1581 return []
1582
1583
Peter Kasting4844e46e2018-02-23 07:27:101584def _CheckUniquePtr(input_api, output_api):
1585 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1586 sources = lambda affected_file: input_api.FilterSourceFile(
1587 affected_file,
1588 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1589 input_api.DEFAULT_BLACK_LIST),
1590 white_list=(file_inclusion_pattern,))
Vaclav Brozeka54c528b2018-04-06 19:23:551591
1592 # Pattern to capture a single "<...>" block of template arguments. It can
1593 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
1594 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
1595 # latter would likely require counting that < and > match, which is not
1596 # expressible in regular languages. Should the need arise, one can introduce
1597 # limited counting (matching up to a total number of nesting depth), which
1598 # should cover all practical cases for already a low nesting limit.
1599 template_arg_pattern = (
1600 r'<[^>]*' # Opening block of <.
1601 r'>([^<]*>)?') # Closing block of >.
1602 # Prefix expressing that whatever follows is not already inside a <...>
1603 # block.
1604 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:101605 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:551606 not_inside_template_arg_pattern
1607 + r'\bstd::unique_ptr'
1608 + template_arg_pattern
1609 + r'\(\)')
1610
1611 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
1612 template_arg_no_array_pattern = (
1613 r'<[^>]*[^]]' # Opening block of <.
1614 r'>([^(<]*[^]]>)?') # Closing block of >.
1615 # Prefix saying that what follows is the start of an expression.
1616 start_of_expr_pattern = r'(=|\breturn|^)\s*'
1617 # Suffix saying that what follows are call parentheses with a non-empty list
1618 # of arguments.
1619 nonempty_arg_list_pattern = r'\(([^)]|$)'
1620 return_construct_pattern = input_api.re.compile(
1621 start_of_expr_pattern
1622 + r'std::unique_ptr'
1623 + template_arg_no_array_pattern
1624 + nonempty_arg_list_pattern)
1625
Vaclav Brozek851d9602018-04-04 16:13:051626 problems_constructor = []
1627 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:101628 for f in input_api.AffectedSourceFiles(sources):
1629 for line_number, line in f.ChangedContents():
1630 # Disallow:
1631 # return std::unique_ptr<T>(foo);
1632 # bar = std::unique_ptr<T>(foo);
1633 # But allow:
1634 # return std::unique_ptr<T[]>(foo);
1635 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozek851d9602018-04-04 16:13:051636 local_path = f.LocalPath()
Peter Kasting4844e46e2018-02-23 07:27:101637 if return_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:051638 problems_constructor.append(
1639 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:101640 # Disallow:
1641 # std::unique_ptr<T>()
1642 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:051643 problems_nullptr.append(
1644 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1645
1646 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:161647 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:051648 errors.append(output_api.PresubmitError(
1649 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:161650 problems_nullptr))
1651 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:051652 errors.append(output_api.PresubmitError(
1653 'The following files use explicit std::unique_ptr constructor.'
1654 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:161655 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:101656 return errors
1657
1658
[email protected]999261d2014-03-03 20:08:081659def _CheckUserActionUpdate(input_api, output_api):
1660 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521661 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081662 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521663 # If actions.xml is already included in the changelist, the PRESUBMIT
1664 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081665 return []
1666
[email protected]999261d2014-03-03 20:08:081667 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1668 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521669 current_actions = None
[email protected]999261d2014-03-03 20:08:081670 for f in input_api.AffectedFiles(file_filter=file_filter):
1671 for line_num, line in f.ChangedContents():
1672 match = input_api.re.search(action_re, line)
1673 if match:
[email protected]2f92dec2014-03-07 19:21:521674 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1675 # loaded only once.
1676 if not current_actions:
1677 with open('tools/metrics/actions/actions.xml') as actions_f:
1678 current_actions = actions_f.read()
1679 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081680 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521681 action = 'name="{0}"'.format(action_name)
1682 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081683 return [output_api.PresubmitPromptWarning(
1684 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521685 'tools/metrics/actions/actions.xml. Please run '
1686 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081687 % (f.LocalPath(), line_num, action_name))]
1688 return []
1689
1690
Daniel Cheng13ca61a882017-08-25 15:11:251691def _ImportJSONCommentEater(input_api):
1692 import sys
1693 sys.path = sys.path + [input_api.os_path.join(
1694 input_api.PresubmitLocalPath(),
1695 'tools', 'json_comment_eater')]
1696 import json_comment_eater
1697 return json_comment_eater
1698
1699
[email protected]99171a92014-06-03 08:44:471700def _GetJSONParseError(input_api, filename, eat_comments=True):
1701 try:
1702 contents = input_api.ReadFile(filename)
1703 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251704 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131705 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471706
1707 input_api.json.loads(contents)
1708 except ValueError as e:
1709 return e
1710 return None
1711
1712
1713def _GetIDLParseError(input_api, filename):
1714 try:
1715 contents = input_api.ReadFile(filename)
1716 idl_schema = input_api.os_path.join(
1717 input_api.PresubmitLocalPath(),
1718 'tools', 'json_schema_compiler', 'idl_schema.py')
1719 process = input_api.subprocess.Popen(
1720 [input_api.python_executable, idl_schema],
1721 stdin=input_api.subprocess.PIPE,
1722 stdout=input_api.subprocess.PIPE,
1723 stderr=input_api.subprocess.PIPE,
1724 universal_newlines=True)
1725 (_, error) = process.communicate(input=contents)
1726 return error or None
1727 except ValueError as e:
1728 return e
1729
1730
1731def _CheckParseErrors(input_api, output_api):
1732 """Check that IDL and JSON files do not contain syntax errors."""
1733 actions = {
1734 '.idl': _GetIDLParseError,
1735 '.json': _GetJSONParseError,
1736 }
[email protected]99171a92014-06-03 08:44:471737 # Most JSON files are preprocessed and support comments, but these do not.
1738 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491739 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471740 ]
1741 # Only run IDL checker on files in these directories.
1742 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491743 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1744 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471745 ]
1746
1747 def get_action(affected_file):
1748 filename = affected_file.LocalPath()
1749 return actions.get(input_api.os_path.splitext(filename)[1])
1750
[email protected]99171a92014-06-03 08:44:471751 def FilterFile(affected_file):
1752 action = get_action(affected_file)
1753 if not action:
1754 return False
1755 path = affected_file.LocalPath()
1756
Sean Kau46e29bc2017-08-28 16:31:161757 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471758 return False
1759
1760 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161761 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471762 return False
1763 return True
1764
1765 results = []
1766 for affected_file in input_api.AffectedFiles(
1767 file_filter=FilterFile, include_deletes=False):
1768 action = get_action(affected_file)
1769 kwargs = {}
1770 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161771 _MatchesFile(input_api, json_no_comments_patterns,
1772 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471773 kwargs['eat_comments'] = False
1774 parse_error = action(input_api,
1775 affected_file.AbsoluteLocalPath(),
1776 **kwargs)
1777 if parse_error:
1778 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1779 (affected_file.LocalPath(), parse_error)))
1780 return results
1781
1782
[email protected]760deea2013-12-10 19:33:491783def _CheckJavaStyle(input_api, output_api):
1784 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471785 import sys
[email protected]760deea2013-12-10 19:33:491786 original_sys_path = sys.path
1787 try:
1788 sys.path = sys.path + [input_api.os_path.join(
1789 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1790 import checkstyle
1791 finally:
1792 # Restore sys.path to what it was before.
1793 sys.path = original_sys_path
1794
1795 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091796 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511797 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491798
1799
Sean Kau46e29bc2017-08-28 16:31:161800def _MatchesFile(input_api, patterns, path):
1801 for pattern in patterns:
1802 if input_api.re.search(pattern, path):
1803 return True
1804 return False
1805
1806
Daniel Cheng7052cdf2017-11-21 19:23:291807def _GetOwnersFilesToCheckForIpcOwners(input_api):
1808 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:171809
Daniel Cheng7052cdf2017-11-21 19:23:291810 Returns:
1811 A dictionary mapping an OWNER file to the list of OWNERS rules it must
1812 contain to cover IPC-related files with noparent reviewer rules.
1813 """
1814 # Whether or not a file affects IPC is (mostly) determined by a simple list
1815 # of filename patterns.
dchenge07de812016-06-20 19:27:171816 file_patterns = [
palmerb19a0932017-01-24 04:00:311817 # Legacy IPC:
dchenge07de812016-06-20 19:27:171818 '*_messages.cc',
1819 '*_messages*.h',
1820 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311821 # Mojo IPC:
dchenge07de812016-06-20 19:27:171822 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:471823 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:171824 '*_struct_traits*.*',
1825 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311826 '*.typemap',
1827 # Android native IPC:
1828 '*.aidl',
1829 # Blink uses a different file naming convention:
1830 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:471831 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:171832 '*StructTraits*.*',
1833 '*TypeConverter*.*',
1834 ]
1835
scottmg7a6ed5ba2016-11-04 18:22:041836 # These third_party directories do not contain IPCs, but contain files
1837 # matching the above patterns, which trigger false positives.
1838 exclude_paths = [
1839 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291840 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041841 ]
1842
dchenge07de812016-06-20 19:27:171843 # Dictionary mapping an OWNERS file path to Patterns.
1844 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1845 # rules ) to a PatternEntry.
1846 # PatternEntry is a dictionary with two keys:
1847 # - 'files': the files that are matched by this pattern
1848 # - 'rules': the per-file rules needed for this pattern
1849 # For example, if we expect OWNERS file to contain rules for *.mojom and
1850 # *_struct_traits*.*, Patterns might look like this:
1851 # {
1852 # '*.mojom': {
1853 # 'files': ...,
1854 # 'rules': [
1855 # 'per-file *.mojom=set noparent',
1856 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1857 # ],
1858 # },
1859 # '*_struct_traits*.*': {
1860 # 'files': ...,
1861 # 'rules': [
1862 # 'per-file *_struct_traits*.*=set noparent',
1863 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1864 # ],
1865 # },
1866 # }
1867 to_check = {}
1868
Daniel Cheng13ca61a882017-08-25 15:11:251869 def AddPatternToCheck(input_file, pattern):
1870 owners_file = input_api.os_path.join(
1871 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1872 if owners_file not in to_check:
1873 to_check[owners_file] = {}
1874 if pattern not in to_check[owners_file]:
1875 to_check[owners_file][pattern] = {
1876 'files': [],
1877 'rules': [
1878 'per-file %s=set noparent' % pattern,
1879 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1880 ]
1881 }
Vaclav Brozekd5de76a2018-03-17 07:57:501882 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:251883
dchenge07de812016-06-20 19:27:171884 # Iterate through the affected files to see what we actually need to check
1885 # for. We should only nag patch authors about per-file rules if a file in that
1886 # directory would match that pattern. If a directory only contains *.mojom
1887 # files and no *_messages*.h files, we should only nag about rules for
1888 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251889 for f in input_api.AffectedFiles(include_deletes=False):
1890 # Manifest files don't have a strong naming convention. Instead, scan
1891 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161892 if (f.LocalPath().endswith('.json') and
1893 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1894 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251895 json_comment_eater = _ImportJSONCommentEater(input_api)
1896 mostly_json_lines = '\n'.join(f.NewContents())
1897 # Comments aren't allowed in strict JSON, so filter them out.
1898 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:431899 try:
1900 json_content = input_api.json.loads(json_lines)
1901 except:
1902 # There's another PRESUBMIT check that already verifies that JSON files
1903 # are not invalid, so no need to emit another warning here.
1904 continue
Daniel Cheng13ca61a882017-08-25 15:11:251905 if 'interface_provider_specs' in json_content:
1906 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171907 for pattern in file_patterns:
1908 if input_api.fnmatch.fnmatch(
1909 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041910 skip = False
1911 for exclude in exclude_paths:
1912 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1913 skip = True
1914 break
1915 if skip:
1916 continue
Daniel Cheng13ca61a882017-08-25 15:11:251917 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171918 break
1919
Daniel Cheng7052cdf2017-11-21 19:23:291920 return to_check
1921
1922
1923def _CheckIpcOwners(input_api, output_api):
1924 """Checks that affected files involving IPC have an IPC OWNERS rule."""
1925 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
1926
1927 if to_check:
1928 # If there are any OWNERS files to check, there are IPC-related changes in
1929 # this CL. Auto-CC the review list.
1930 output_api.AppendCC('[email protected]')
1931
1932 # Go through the OWNERS files to check, filtering out rules that are already
1933 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:171934 for owners_file, patterns in to_check.iteritems():
1935 try:
1936 with file(owners_file) as f:
1937 lines = set(f.read().splitlines())
1938 for entry in patterns.itervalues():
1939 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1940 ]
1941 except IOError:
1942 # No OWNERS file, so all the rules are definitely missing.
1943 continue
1944
1945 # All the remaining lines weren't found in OWNERS files, so emit an error.
1946 errors = []
1947 for owners_file, patterns in to_check.iteritems():
1948 missing_lines = []
1949 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:501950 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:171951 missing_lines.extend(entry['rules'])
1952 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1953 if missing_lines:
1954 errors.append(
Daniel Cheng52111692017-06-14 08:00:591955 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171956 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1957
1958 results = []
1959 if errors:
vabrf5ce3bf92016-07-11 14:52:411960 if input_api.is_committing:
1961 output = output_api.PresubmitError
1962 else:
1963 output = output_api.PresubmitPromptWarning
1964 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591965 'Found OWNERS files that need to be updated for IPC security ' +
1966 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171967 long_text='\n\n'.join(errors)))
1968
1969 return results
1970
1971
jbriance9e12f162016-11-25 07:57:501972def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311973 """Checks that added or removed lines in non third party affected
1974 header files do not lead to new useless class or struct forward
1975 declaration.
jbriance9e12f162016-11-25 07:57:501976 """
1977 results = []
1978 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1979 input_api.re.MULTILINE)
1980 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1981 input_api.re.MULTILINE)
1982 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311983 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191984 not f.LocalPath().startswith('third_party/blink') and
1985 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311986 not f.LocalPath().startswith('third_party/WebKit') and
1987 not f.LocalPath().startswith('third_party\\WebKit')):
1988 continue
1989
jbriance9e12f162016-11-25 07:57:501990 if not f.LocalPath().endswith('.h'):
1991 continue
1992
1993 contents = input_api.ReadFile(f)
1994 fwd_decls = input_api.re.findall(class_pattern, contents)
1995 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1996
1997 useless_fwd_decls = []
1998 for decl in fwd_decls:
1999 count = sum(1 for _ in input_api.re.finditer(
2000 r'\b%s\b' % input_api.re.escape(decl), contents))
2001 if count == 1:
2002 useless_fwd_decls.append(decl)
2003
2004 if not useless_fwd_decls:
2005 continue
2006
2007 for line in f.GenerateScmDiff().splitlines():
2008 if (line.startswith('-') and not line.startswith('--') or
2009 line.startswith('+') and not line.startswith('++')):
2010 for decl in useless_fwd_decls:
2011 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
2012 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:242013 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:502014 (f.LocalPath(), decl)))
2015 useless_fwd_decls.remove(decl)
2016
2017 return results
2018
2019
dskiba88634f4e2015-08-14 23:03:292020def _CheckAndroidToastUsage(input_api, output_api):
2021 """Checks that code uses org.chromium.ui.widget.Toast instead of
2022 android.widget.Toast (Chromium Toast doesn't force hardware
2023 acceleration on low-end devices, saving memory).
2024 """
2025 toast_import_pattern = input_api.re.compile(
2026 r'^import android\.widget\.Toast;$')
2027
2028 errors = []
2029
2030 sources = lambda affected_file: input_api.FilterSourceFile(
2031 affected_file,
2032 black_list=(_EXCLUDED_PATHS +
2033 _TEST_CODE_EXCLUDED_PATHS +
2034 input_api.DEFAULT_BLACK_LIST +
2035 (r'^chromecast[\\\/].*',
2036 r'^remoting[\\\/].*')),
2037 white_list=(r'.*\.java$',))
2038
2039 for f in input_api.AffectedSourceFiles(sources):
2040 for line_num, line in f.ChangedContents():
2041 if toast_import_pattern.search(line):
2042 errors.append("%s:%d" % (f.LocalPath(), line_num))
2043
2044 results = []
2045
2046 if errors:
2047 results.append(output_api.PresubmitError(
2048 'android.widget.Toast usage is detected. Android toasts use hardware'
2049 ' acceleration, and can be\ncostly on low-end devices. Please use'
2050 ' org.chromium.ui.widget.Toast instead.\n'
2051 'Contact [email protected] if you have any questions.',
2052 errors))
2053
2054 return results
2055
2056
dgnaa68d5e2015-06-10 10:08:222057def _CheckAndroidCrLogUsage(input_api, output_api):
2058 """Checks that new logs using org.chromium.base.Log:
2059 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:512060 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:222061 """
pkotwicza1dd0b002016-05-16 14:41:042062
torne89540622017-03-24 19:41:302063 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:042064 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:302065 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:042066 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:302067 # WebView license viewer code cannot depend on //base; used in stub APK.
2068 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
2069 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:042070 ]
2071
dgnaa68d5e2015-06-10 10:08:222072 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:122073 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
2074 class_in_base_pattern = input_api.re.compile(
2075 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
2076 has_some_log_import_pattern = input_api.re.compile(
2077 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222078 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:122079 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:222080 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:512081 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:222082 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222083
Vincent Scheib16d7b272015-09-15 18:09:072084 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:222085 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:042086 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
2087 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:122088
dgnaa68d5e2015-06-10 10:08:222089 tag_decl_errors = []
2090 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:122091 tag_errors = []
dgn38736db2015-09-18 19:20:512092 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:122093 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:222094
2095 for f in input_api.AffectedSourceFiles(sources):
2096 file_content = input_api.ReadFile(f)
2097 has_modified_logs = False
2098
2099 # Per line checks
dgn87d9fb62015-06-12 09:15:122100 if (cr_log_import_pattern.search(file_content) or
2101 (class_in_base_pattern.search(file_content) and
2102 not has_some_log_import_pattern.search(file_content))):
2103 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:222104 for line_num, line in f.ChangedContents():
2105
2106 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:122107 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:222108 if match:
2109 has_modified_logs = True
2110
2111 # Make sure it uses "TAG"
2112 if not match.group('tag') == 'TAG':
2113 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:122114 else:
2115 # Report non cr Log function calls in changed lines
2116 for line_num, line in f.ChangedContents():
2117 if log_call_pattern.search(line):
2118 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:222119
2120 # Per file checks
2121 if has_modified_logs:
2122 # Make sure the tag is using the "cr" prefix and is not too long
2123 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:512124 tag_name = match.group('name') if match else None
2125 if not tag_name:
dgnaa68d5e2015-06-10 10:08:222126 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512127 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:222128 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512129 elif '.' in tag_name:
2130 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:222131
2132 results = []
2133 if tag_decl_errors:
2134 results.append(output_api.PresubmitPromptWarning(
2135 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:512136 '"private static final String TAG = "<package tag>".\n'
2137 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222138 tag_decl_errors))
2139
2140 if tag_length_errors:
2141 results.append(output_api.PresubmitError(
2142 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:512143 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222144 tag_length_errors))
2145
2146 if tag_errors:
2147 results.append(output_api.PresubmitPromptWarning(
2148 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
2149 tag_errors))
2150
dgn87d9fb62015-06-12 09:15:122151 if util_log_errors:
dgn4401aa52015-04-29 16:26:172152 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:122153 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
2154 util_log_errors))
2155
dgn38736db2015-09-18 19:20:512156 if tag_with_dot_errors:
2157 results.append(output_api.PresubmitPromptWarning(
2158 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
2159 tag_with_dot_errors))
2160
dgn4401aa52015-04-29 16:26:172161 return results
2162
2163
Yoland Yanb92fa522017-08-28 17:37:062164def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
2165 """Checks that junit.framework.* is no longer used."""
2166 deprecated_junit_framework_pattern = input_api.re.compile(
2167 r'^import junit\.framework\..*;',
2168 input_api.re.MULTILINE)
2169 sources = lambda x: input_api.FilterSourceFile(
2170 x, white_list=(r'.*\.java$',), black_list=None)
2171 errors = []
2172 for f in input_api.AffectedFiles(sources):
2173 for line_num, line in f.ChangedContents():
2174 if deprecated_junit_framework_pattern.search(line):
2175 errors.append("%s:%d" % (f.LocalPath(), line_num))
2176
2177 results = []
2178 if errors:
2179 results.append(output_api.PresubmitError(
2180 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
2181 '(org.junit.*) from //third_party/junit. Contact [email protected]'
2182 ' if you have any question.', errors))
2183 return results
2184
2185
2186def _CheckAndroidTestJUnitInheritance(input_api, output_api):
2187 """Checks that if new Java test classes have inheritance.
2188 Either the new test class is JUnit3 test or it is a JUnit4 test class
2189 with a base class, either case is undesirable.
2190 """
2191 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
2192
2193 sources = lambda x: input_api.FilterSourceFile(
2194 x, white_list=(r'.*Test\.java$',), black_list=None)
2195 errors = []
2196 for f in input_api.AffectedFiles(sources):
2197 if not f.OldContents():
2198 class_declaration_start_flag = False
2199 for line_num, line in f.ChangedContents():
2200 if class_declaration_pattern.search(line):
2201 class_declaration_start_flag = True
2202 if class_declaration_start_flag and ' extends ' in line:
2203 errors.append('%s:%d' % (f.LocalPath(), line_num))
2204 if '{' in line:
2205 class_declaration_start_flag = False
2206
2207 results = []
2208 if errors:
2209 results.append(output_api.PresubmitPromptWarning(
2210 'The newly created files include Test classes that inherits from base'
2211 ' class. Please do not use inheritance in JUnit4 tests or add new'
2212 ' JUnit3 tests. Contact [email protected] if you have any'
2213 ' questions.', errors))
2214 return results
2215
yolandyan45001472016-12-21 21:12:422216def _CheckAndroidTestAnnotationUsage(input_api, output_api):
2217 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
2218 deprecated_annotation_import_pattern = input_api.re.compile(
2219 r'^import android\.test\.suitebuilder\.annotation\..*;',
2220 input_api.re.MULTILINE)
2221 sources = lambda x: input_api.FilterSourceFile(
2222 x, white_list=(r'.*\.java$',), black_list=None)
2223 errors = []
2224 for f in input_api.AffectedFiles(sources):
2225 for line_num, line in f.ChangedContents():
2226 if deprecated_annotation_import_pattern.search(line):
2227 errors.append("%s:%d" % (f.LocalPath(), line_num))
2228
2229 results = []
2230 if errors:
2231 results.append(output_api.PresubmitError(
2232 'Annotations in android.test.suitebuilder.annotation have been'
2233 ' deprecated since API level 24. Please use android.support.test.filters'
2234 ' from //third_party/android_support_test_runner:runner_java instead.'
2235 ' Contact [email protected] if you have any questions.', errors))
2236 return results
2237
2238
agrieve7b6479d82015-10-07 14:24:222239def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
2240 """Checks if MDPI assets are placed in a correct directory."""
2241 file_filter = lambda f: (f.LocalPath().endswith('.png') and
2242 ('/res/drawable/' in f.LocalPath() or
2243 '/res/drawable-ldrtl/' in f.LocalPath()))
2244 errors = []
2245 for f in input_api.AffectedFiles(include_deletes=False,
2246 file_filter=file_filter):
2247 errors.append(' %s' % f.LocalPath())
2248
2249 results = []
2250 if errors:
2251 results.append(output_api.PresubmitError(
2252 'MDPI assets should be placed in /res/drawable-mdpi/ or '
2253 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
2254 '/res/drawable-ldrtl/.\n'
2255 'Contact [email protected] if you have questions.', errors))
2256 return results
2257
2258
Nate Fischer535972b2017-09-16 01:06:182259def _CheckAndroidWebkitImports(input_api, output_api):
2260 """Checks that code uses org.chromium.base.Callback instead of
2261 android.widget.ValueCallback except in the WebView glue layer.
2262 """
2263 valuecallback_import_pattern = input_api.re.compile(
2264 r'^import android\.webkit\.ValueCallback;$')
2265
2266 errors = []
2267
2268 sources = lambda affected_file: input_api.FilterSourceFile(
2269 affected_file,
2270 black_list=(_EXCLUDED_PATHS +
2271 _TEST_CODE_EXCLUDED_PATHS +
2272 input_api.DEFAULT_BLACK_LIST +
2273 (r'^android_webview[\\\/]glue[\\\/].*',)),
2274 white_list=(r'.*\.java$',))
2275
2276 for f in input_api.AffectedSourceFiles(sources):
2277 for line_num, line in f.ChangedContents():
2278 if valuecallback_import_pattern.search(line):
2279 errors.append("%s:%d" % (f.LocalPath(), line_num))
2280
2281 results = []
2282
2283 if errors:
2284 results.append(output_api.PresubmitError(
2285 'android.webkit.ValueCallback usage is detected outside of the glue'
2286 ' layer. To stay compatible with the support library, android.webkit.*'
2287 ' classes should only be used inside the glue layer and'
2288 ' org.chromium.base.Callback should be used instead.',
2289 errors))
2290
2291 return results
2292
2293
agrievef32bcc72016-04-04 14:57:402294class PydepsChecker(object):
2295 def __init__(self, input_api, pydeps_files):
2296 self._file_cache = {}
2297 self._input_api = input_api
2298 self._pydeps_files = pydeps_files
2299
2300 def _LoadFile(self, path):
2301 """Returns the list of paths within a .pydeps file relative to //."""
2302 if path not in self._file_cache:
2303 with open(path) as f:
2304 self._file_cache[path] = f.read()
2305 return self._file_cache[path]
2306
2307 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
2308 """Returns an interable of paths within the .pydep, relativized to //."""
2309 os_path = self._input_api.os_path
2310 pydeps_dir = os_path.dirname(pydeps_path)
2311 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2312 if not l.startswith('*'))
2313 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2314
2315 def _CreateFilesToPydepsMap(self):
2316 """Returns a map of local_path -> list_of_pydeps."""
2317 ret = {}
2318 for pydep_local_path in self._pydeps_files:
2319 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2320 ret.setdefault(path, []).append(pydep_local_path)
2321 return ret
2322
2323 def ComputeAffectedPydeps(self):
2324 """Returns an iterable of .pydeps files that might need regenerating."""
2325 affected_pydeps = set()
2326 file_to_pydeps_map = None
2327 for f in self._input_api.AffectedFiles(include_deletes=True):
2328 local_path = f.LocalPath()
2329 if local_path == 'DEPS':
2330 return self._pydeps_files
2331 elif local_path.endswith('.pydeps'):
2332 if local_path in self._pydeps_files:
2333 affected_pydeps.add(local_path)
2334 elif local_path.endswith('.py'):
2335 if file_to_pydeps_map is None:
2336 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2337 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2338 return affected_pydeps
2339
2340 def DetermineIfStale(self, pydeps_path):
2341 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412342 import difflib
John Budorick47ca3fe2018-02-10 00:53:102343 import os
2344
agrievef32bcc72016-04-04 14:57:402345 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2346 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:102347 env = dict(os.environ)
2348 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:402349 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:102350 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412351 old_contents = old_pydeps_data[2:]
2352 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402353 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412354 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402355
2356
2357def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2358 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:402359 # This check is for Python dependency lists (.pydeps files), and involves
2360 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
2361 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:282362 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002363 return []
Mostyn Bramley-Moore6b427322017-12-21 22:11:022364 # TODO(agrieve): Update when there's a better way to detect
2365 # this: crbug.com/570091
agrievef32bcc72016-04-04 14:57:402366 is_android = input_api.os_path.exists('third_party/android_tools')
2367 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2368 results = []
2369 # First, check for new / deleted .pydeps.
2370 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:032371 # Check whether we are running the presubmit check for a file in src.
2372 # f.LocalPath is relative to repo (src, or internal repo).
2373 # os_path.exists is relative to src repo.
2374 # Therefore if os_path.exists is true, it means f.LocalPath is relative
2375 # to src and we can conclude that the pydeps is in src.
2376 if input_api.os_path.exists(f.LocalPath()):
2377 if f.LocalPath().endswith('.pydeps'):
2378 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2379 results.append(output_api.PresubmitError(
2380 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2381 'remove %s' % f.LocalPath()))
2382 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2383 results.append(output_api.PresubmitError(
2384 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2385 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:402386
2387 if results:
2388 return results
2389
2390 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2391
2392 for pydep_path in checker.ComputeAffectedPydeps():
2393 try:
phajdan.jr0d9878552016-11-04 10:49:412394 result = checker.DetermineIfStale(pydep_path)
2395 if result:
2396 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402397 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412398 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2399 'To regenerate, run:\n\n %s' %
2400 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402401 except input_api.subprocess.CalledProcessError as error:
2402 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2403 long_text=error.output)]
2404
2405 return results
2406
2407
glidere61efad2015-02-18 17:39:432408def _CheckSingletonInHeaders(input_api, output_api):
2409 """Checks to make sure no header files have |Singleton<|."""
2410 def FileFilter(affected_file):
2411 # It's ok for base/memory/singleton.h to have |Singleton<|.
2412 black_list = (_EXCLUDED_PATHS +
2413 input_api.DEFAULT_BLACK_LIST +
Michael Warrese4451492018-03-07 04:42:472414 (r"^base[\\\/]memory[\\\/]singleton\.h$",
2415 r"^net[\\\/]quic[\\\/]platform[\\\/]impl[\\\/]"
2416 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:432417 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2418
sergeyu34d21222015-09-16 00:11:442419 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432420 files = []
2421 for f in input_api.AffectedSourceFiles(FileFilter):
2422 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2423 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2424 contents = input_api.ReadFile(f)
2425 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242426 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432427 pattern.search(line)):
2428 files.append(f)
2429 break
2430
2431 if files:
yolandyandaabc6d2016-04-18 18:29:392432 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442433 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432434 'Please move them to an appropriate source file so that the ' +
2435 'template gets instantiated in a single compilation unit.',
2436 files) ]
2437 return []
2438
2439
[email protected]fd20b902014-05-09 02:14:532440_DEPRECATED_CSS = [
2441 # Values
2442 ( "-webkit-box", "flex" ),
2443 ( "-webkit-inline-box", "inline-flex" ),
2444 ( "-webkit-flex", "flex" ),
2445 ( "-webkit-inline-flex", "inline-flex" ),
2446 ( "-webkit-min-content", "min-content" ),
2447 ( "-webkit-max-content", "max-content" ),
2448
2449 # Properties
2450 ( "-webkit-background-clip", "background-clip" ),
2451 ( "-webkit-background-origin", "background-origin" ),
2452 ( "-webkit-background-size", "background-size" ),
2453 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442454 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532455
2456 # Functions
2457 ( "-webkit-gradient", "gradient" ),
2458 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2459 ( "-webkit-linear-gradient", "linear-gradient" ),
2460 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2461 ( "-webkit-radial-gradient", "radial-gradient" ),
2462 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2463]
2464
dbeam1ec68ac2016-12-15 05:22:242465def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532466 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252467 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342468 documentation and iOS CSS for dom distiller
2469 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252470 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532471 results = []
dbeam070cfe62014-10-22 06:44:022472 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252473 black_list = (_EXCLUDED_PATHS +
2474 _TEST_CODE_EXCLUDED_PATHS +
2475 input_api.DEFAULT_BLACK_LIST +
2476 (r"^chrome/common/extensions/docs",
2477 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342478 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442479 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252480 r"^native_client_sdk"))
2481 file_filter = lambda f: input_api.FilterSourceFile(
2482 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532483 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2484 for line_num, line in fpath.ChangedContents():
2485 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022486 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532487 results.append(output_api.PresubmitError(
2488 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2489 (fpath.LocalPath(), line_num, deprecated_value, value)))
2490 return results
2491
mohan.reddyf21db962014-10-16 12:26:472492
dbeam070cfe62014-10-22 06:44:022493_DEPRECATED_JS = [
2494 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2495 ( "__defineGetter__", "Object.defineProperty" ),
2496 ( "__defineSetter__", "Object.defineProperty" ),
2497]
2498
dbeam1ec68ac2016-12-15 05:22:242499def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022500 """Make sure that we don't use deprecated JS in Chrome code."""
2501 results = []
2502 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2503 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2504 input_api.DEFAULT_BLACK_LIST)
2505 file_filter = lambda f: input_api.FilterSourceFile(
2506 f, white_list=file_inclusion_pattern, black_list=black_list)
2507 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2508 for lnum, line in fpath.ChangedContents():
2509 for (deprecated, replacement) in _DEPRECATED_JS:
2510 if deprecated in line:
2511 results.append(output_api.PresubmitError(
2512 "%s:%d: Use of deprecated JS %s, use %s instead" %
2513 (fpath.LocalPath(), lnum, deprecated, replacement)))
2514 return results
2515
dpapadd651231d82017-07-21 02:44:472516def _CheckForRiskyJsArrowFunction(line_number, line):
2517 if ' => ' in line:
2518 return "line %d, is using an => (arrow) function\n %s\n" % (
2519 line_number, line)
2520 return ''
2521
2522def _CheckForRiskyJsConstLet(input_api, line_number, line):
2523 if input_api.re.match('^\s*(const|let)\s', line):
2524 return "line %d, is using const/let keyword\n %s\n" % (
2525 line_number, line)
2526 return ''
dbeam070cfe62014-10-22 06:44:022527
dbeam1ec68ac2016-12-15 05:22:242528def _CheckForRiskyJsFeatures(input_api, output_api):
2529 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002530 # 'ui/webui/resources/cr_components are not allowed on ios'
2531 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572532 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002533 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472534 results = []
dbeam1ec68ac2016-12-15 05:22:242535 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472536 arrow_error_lines = []
2537 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242538 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472539 arrow_error_lines += filter(None, [
2540 _CheckForRiskyJsArrowFunction(lnum, line),
2541 ])
dbeam1ec68ac2016-12-15 05:22:242542
dpapadd651231d82017-07-21 02:44:472543 const_let_error_lines += filter(None, [
2544 _CheckForRiskyJsConstLet(input_api, lnum, line),
2545 ])
dbeam1ec68ac2016-12-15 05:22:242546
dpapadd651231d82017-07-21 02:44:472547 if arrow_error_lines:
2548 arrow_error_lines = map(
2549 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2550 results.append(
2551 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2552"""
2553Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242554%s
2555Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2556https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472557""" % f.LocalPath()
2558 ])))
dbeam1ec68ac2016-12-15 05:22:242559
dpapadd651231d82017-07-21 02:44:472560 if const_let_error_lines:
2561 const_let_error_lines = map(
2562 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2563 results.append(
2564 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2565"""
2566Use of const/let keywords detected in:
2567%s
2568Please ensure your code does not run on iOS9 because const/let is not fully
2569supported.
2570https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2571https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2572""" % f.LocalPath()
2573 ])))
2574
2575 return results
dbeam1ec68ac2016-12-15 05:22:242576
rlanday6802cf632017-05-30 17:48:362577def _CheckForRelativeIncludes(input_api, output_api):
2578 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2579 import sys
2580 original_sys_path = sys.path
2581 try:
2582 sys.path = sys.path + [input_api.os_path.join(
2583 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2584 from cpp_checker import CppChecker
2585 finally:
2586 # Restore sys.path to what it was before.
2587 sys.path = original_sys_path
2588
2589 bad_files = {}
2590 for f in input_api.AffectedFiles(include_deletes=False):
2591 if (f.LocalPath().startswith('third_party') and
2592 not f.LocalPath().startswith('third_party/WebKit') and
2593 not f.LocalPath().startswith('third_party\\WebKit')):
2594 continue
2595
2596 if not CppChecker.IsCppFile(f.LocalPath()):
2597 continue
2598
Vaclav Brozekd5de76a2018-03-17 07:57:502599 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:362600 if "#include" in line and "../" in line]
2601 if not relative_includes:
2602 continue
2603 bad_files[f.LocalPath()] = relative_includes
2604
2605 if not bad_files:
2606 return []
2607
2608 error_descriptions = []
2609 for file_path, bad_lines in bad_files.iteritems():
2610 error_description = file_path
2611 for line in bad_lines:
2612 error_description += '\n ' + line
2613 error_descriptions.append(error_description)
2614
2615 results = []
2616 results.append(output_api.PresubmitError(
2617 'You added one or more relative #include paths (including "../").\n'
2618 'These shouldn\'t be used because they can be used to include headers\n'
2619 'from code that\'s not correctly specified as a dependency in the\n'
2620 'relevant BUILD.gn file(s).',
2621 error_descriptions))
2622
2623 return results
2624
Takeshi Yoshinoe387aa32017-08-02 13:16:132625
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202626def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2627 if not isinstance(key, ast.Str):
2628 return 'Key at line %d must be a string literal' % key.lineno
2629 if not isinstance(value, ast.Dict):
2630 return 'Value at line %d must be a dict' % value.lineno
2631 if len(value.keys) != 1:
2632 return 'Dict at line %d must have single entry' % value.lineno
2633 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2634 return (
2635 'Entry at line %d must have a string literal \'filepath\' as key' %
2636 value.lineno)
2637 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132638
Takeshi Yoshinoe387aa32017-08-02 13:16:132639
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202640def _CheckWatchlistsEntrySyntax(key, value, ast):
2641 if not isinstance(key, ast.Str):
2642 return 'Key at line %d must be a string literal' % key.lineno
2643 if not isinstance(value, ast.List):
2644 return 'Value at line %d must be a list' % value.lineno
2645 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132646
Takeshi Yoshinoe387aa32017-08-02 13:16:132647
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202648def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2649 mismatch_template = (
2650 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2651 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132652
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202653 i = 0
2654 last_key = ''
2655 while True:
2656 if i >= len(wd_dict.keys):
2657 if i >= len(w_dict.keys):
2658 return None
2659 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2660 elif i >= len(w_dict.keys):
2661 return (
2662 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132663
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202664 wd_key = wd_dict.keys[i]
2665 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132666
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202667 result = _CheckWatchlistDefinitionsEntrySyntax(
2668 wd_key, wd_dict.values[i], ast)
2669 if result is not None:
2670 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132671
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202672 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2673 if result is not None:
2674 return 'Bad entry in WATCHLISTS dict: %s' % result
2675
2676 if wd_key.s != w_key.s:
2677 return mismatch_template % (
2678 '%s at line %d' % (wd_key.s, wd_key.lineno),
2679 '%s at line %d' % (w_key.s, w_key.lineno))
2680
2681 if wd_key.s < last_key:
2682 return (
2683 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2684 (wd_key.lineno, w_key.lineno))
2685 last_key = wd_key.s
2686
2687 i = i + 1
2688
2689
2690def _CheckWATCHLISTSSyntax(expression, ast):
2691 if not isinstance(expression, ast.Expression):
2692 return 'WATCHLISTS file must contain a valid expression'
2693 dictionary = expression.body
2694 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2695 return 'WATCHLISTS file must have single dict with exactly two entries'
2696
2697 first_key = dictionary.keys[0]
2698 first_value = dictionary.values[0]
2699 second_key = dictionary.keys[1]
2700 second_value = dictionary.values[1]
2701
2702 if (not isinstance(first_key, ast.Str) or
2703 first_key.s != 'WATCHLIST_DEFINITIONS' or
2704 not isinstance(first_value, ast.Dict)):
2705 return (
2706 'The first entry of the dict in WATCHLISTS file must be '
2707 'WATCHLIST_DEFINITIONS dict')
2708
2709 if (not isinstance(second_key, ast.Str) or
2710 second_key.s != 'WATCHLISTS' or
2711 not isinstance(second_value, ast.Dict)):
2712 return (
2713 'The second entry of the dict in WATCHLISTS file must be '
2714 'WATCHLISTS dict')
2715
2716 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132717
2718
2719def _CheckWATCHLISTS(input_api, output_api):
2720 for f in input_api.AffectedFiles(include_deletes=False):
2721 if f.LocalPath() == 'WATCHLISTS':
2722 contents = input_api.ReadFile(f, 'r')
2723
2724 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202725 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132726 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202727 # Get an AST tree for it and scan the tree for detailed style checking.
2728 expression = input_api.ast.parse(
2729 contents, filename='WATCHLISTS', mode='eval')
2730 except ValueError as e:
2731 return [output_api.PresubmitError(
2732 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2733 except SyntaxError as e:
2734 return [output_api.PresubmitError(
2735 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2736 except TypeError as e:
2737 return [output_api.PresubmitError(
2738 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132739
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202740 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2741 if result is not None:
2742 return [output_api.PresubmitError(result)]
2743 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132744
2745 return []
2746
2747
dgnaa68d5e2015-06-10 10:08:222748def _AndroidSpecificOnUploadChecks(input_api, output_api):
2749 """Groups checks that target android code."""
2750 results = []
dgnaa68d5e2015-06-10 10:08:222751 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222752 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292753 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062754 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2755 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422756 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182757 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222758 return results
2759
2760
[email protected]22c9bd72011-03-27 16:47:392761def _CommonChecks(input_api, output_api):
2762 """Checks common to both upload and commit."""
2763 results = []
2764 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382765 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542766 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:082767
2768 author = input_api.change.author_email
2769 if author and author not in _KNOWN_ROBOTS:
2770 results.extend(
2771 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
2772
[email protected]55459852011-08-10 15:17:192773 results.extend(
[email protected]760deea2013-12-10 19:33:492774 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:232775 results.extend(
2776 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542777 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182778 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522779 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222780 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442781 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592782 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062783 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122784 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182785 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222786 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302787 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492788 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032789 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492790 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442791 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272792 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072793 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542794 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442795 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392796 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552797 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042798 results.extend(
2799 input_api.canned_checks.CheckChangeHasNoTabs(
2800 input_api,
2801 output_api,
2802 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402803 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162804 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082805 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242806 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2807 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472808 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042809 results.extend(_CheckForIPCRules(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:142810 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232811 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432812 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402813 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152814 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172815 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502816 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242817 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362818 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132819 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432820 results.extend(input_api.RunTests(
2821 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242822
Vaclav Brozekcdc7defb2018-03-20 09:54:352823 for f in input_api.AffectedFiles():
2824 path, name = input_api.os_path.split(f.LocalPath())
2825 if name == 'PRESUBMIT.py':
2826 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
2827 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2828 input_api, output_api, full_path,
2829 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392830 return results
[email protected]1f7b4172010-01-28 01:17:342831
[email protected]b337cb5b2011-01-23 21:24:052832
[email protected]b8079ae4a2012-12-05 19:56:492833def _CheckPatchFiles(input_api, output_api):
2834 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2835 if f.LocalPath().endswith(('.orig', '.rej'))]
2836 if problems:
2837 return [output_api.PresubmitError(
2838 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032839 else:
2840 return []
[email protected]b8079ae4a2012-12-05 19:56:492841
2842
Kent Tamura5a8755d2017-06-29 23:37:072843def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212844 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2845 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2846 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072847 include_re = input_api.re.compile(
2848 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2849 extension_re = input_api.re.compile(r'\.[a-z]+$')
2850 errors = []
2851 for f in input_api.AffectedFiles():
2852 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2853 continue
2854 found_line_number = None
2855 found_macro = None
2856 for line_num, line in f.ChangedContents():
2857 match = macro_re.search(line)
2858 if match:
2859 found_line_number = line_num
2860 found_macro = match.group(2)
2861 break
2862 if not found_line_number:
2863 continue
2864
2865 found_include = False
2866 for line in f.NewContents():
2867 if include_re.search(line):
2868 found_include = True
2869 break
2870 if found_include:
2871 continue
2872
2873 if not f.LocalPath().endswith('.h'):
2874 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2875 try:
2876 content = input_api.ReadFile(primary_header_path, 'r')
2877 if include_re.search(content):
2878 continue
2879 except IOError:
2880 pass
2881 errors.append('%s:%d %s macro is used without including build/'
2882 'build_config.h.'
2883 % (f.LocalPath(), found_line_number, found_macro))
2884 if errors:
2885 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2886 return []
2887
2888
[email protected]b00342e7f2013-03-26 16:21:542889def _DidYouMeanOSMacro(bad_macro):
2890 try:
2891 return {'A': 'OS_ANDROID',
2892 'B': 'OS_BSD',
2893 'C': 'OS_CHROMEOS',
2894 'F': 'OS_FREEBSD',
2895 'L': 'OS_LINUX',
2896 'M': 'OS_MACOSX',
2897 'N': 'OS_NACL',
2898 'O': 'OS_OPENBSD',
2899 'P': 'OS_POSIX',
2900 'S': 'OS_SOLARIS',
2901 'W': 'OS_WIN'}[bad_macro[3].upper()]
2902 except KeyError:
2903 return ''
2904
2905
2906def _CheckForInvalidOSMacrosInFile(input_api, f):
2907 """Check for sensible looking, totally invalid OS macros."""
2908 preprocessor_statement = input_api.re.compile(r'^\s*#')
2909 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2910 results = []
2911 for lnum, line in f.ChangedContents():
2912 if preprocessor_statement.search(line):
2913 for match in os_macro.finditer(line):
2914 if not match.group(1) in _VALID_OS_MACROS:
2915 good = _DidYouMeanOSMacro(match.group(1))
2916 did_you_mean = ' (did you mean %s?)' % good if good else ''
2917 results.append(' %s:%d %s%s' % (f.LocalPath(),
2918 lnum,
2919 match.group(1),
2920 did_you_mean))
2921 return results
2922
2923
2924def _CheckForInvalidOSMacros(input_api, output_api):
2925 """Check all affected files for invalid OS macros."""
2926 bad_macros = []
2927 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472928 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542929 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2930
2931 if not bad_macros:
2932 return []
2933
2934 return [output_api.PresubmitError(
2935 'Possibly invalid OS macro[s] found. Please fix your code\n'
2936 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2937
lliabraa35bab3932014-10-01 12:16:442938
2939def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2940 """Check all affected files for invalid "if defined" macros."""
2941 ALWAYS_DEFINED_MACROS = (
2942 "TARGET_CPU_PPC",
2943 "TARGET_CPU_PPC64",
2944 "TARGET_CPU_68K",
2945 "TARGET_CPU_X86",
2946 "TARGET_CPU_ARM",
2947 "TARGET_CPU_MIPS",
2948 "TARGET_CPU_SPARC",
2949 "TARGET_CPU_ALPHA",
2950 "TARGET_IPHONE_SIMULATOR",
2951 "TARGET_OS_EMBEDDED",
2952 "TARGET_OS_IPHONE",
2953 "TARGET_OS_MAC",
2954 "TARGET_OS_UNIX",
2955 "TARGET_OS_WIN32",
2956 )
2957 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2958 results = []
2959 for lnum, line in f.ChangedContents():
2960 for match in ifdef_macro.finditer(line):
2961 if match.group(1) in ALWAYS_DEFINED_MACROS:
2962 always_defined = ' %s is always defined. ' % match.group(1)
2963 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2964 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2965 lnum,
2966 always_defined,
2967 did_you_mean))
2968 return results
2969
2970
2971def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2972 """Check all affected files for invalid "if defined" macros."""
2973 bad_macros = []
2974 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212975 if f.LocalPath().startswith('third_party/sqlite/'):
2976 continue
lliabraa35bab3932014-10-01 12:16:442977 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2978 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2979
2980 if not bad_macros:
2981 return []
2982
2983 return [output_api.PresubmitError(
2984 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2985 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2986 bad_macros)]
2987
2988
mlamouria82272622014-09-16 18:45:042989def _CheckForIPCRules(input_api, output_api):
2990 """Check for same IPC rules described in
2991 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2992 """
2993 base_pattern = r'IPC_ENUM_TRAITS\('
2994 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2995 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2996
2997 problems = []
2998 for f in input_api.AffectedSourceFiles(None):
2999 local_path = f.LocalPath()
3000 if not local_path.endswith('.h'):
3001 continue
3002 for line_number, line in f.ChangedContents():
3003 if inclusion_pattern.search(line) and not comment_pattern.search(line):
3004 problems.append(
3005 '%s:%d\n %s' % (local_path, line_number, line.strip()))
3006
3007 if problems:
3008 return [output_api.PresubmitPromptWarning(
3009 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
3010 else:
3011 return []
3012
[email protected]b00342e7f2013-03-26 16:21:543013
Daniel Bratell8ba52722018-03-02 16:06:143014def _CheckForIncludeGuards(input_api, output_api):
3015 """Check that header files have proper guards against multiple inclusion.
3016 If a file should not have such guards (and it probably should) then it
3017 should include the string "no-include-guard-because-multiply-included".
3018 """
3019 def is_header_file(f):
3020 return f.LocalPath().endswith('.h')
3021
3022 def replace_special_with_underscore(string):
3023 return input_api.re.sub(r'[\\/.-]', '_', string)
3024
3025 errors = []
3026
3027 for f in input_api.AffectedSourceFiles(is_header_file):
3028 guard_name = None
3029 guard_line_number = None
3030 seen_guard_end = False
3031
3032 file_with_path = input_api.os_path.normpath(f.LocalPath())
3033 base_file_name = input_api.os_path.splitext(
3034 input_api.os_path.basename(file_with_path))[0]
3035 upper_base_file_name = base_file_name.upper()
3036
3037 expected_guard = replace_special_with_underscore(
3038 file_with_path.upper() + '_')
3039 expected_guard_if_blink = base_file_name + '_h'
3040
3041 # For "path/elem/file_name.h" we should really only accept
3042 # PATH_ELEM_FILE_NAME_H_ per coding style or, if Blink,
3043 # file_name_h. Unfortunately there are too many (1000+) files
3044 # with slight deviations from the coding style. Since the most
3045 # important part is that the include guard is there, and that it's
3046 # unique, not the name, this check is forgiving for existing files.
3047 #
3048 # As code becomes more uniform, this could be made stricter.
3049
3050 guard_name_pattern_list = [
3051 # Anything with the right suffix (maybe with an extra _).
3052 r'\w+_H__?',
3053
3054 # To cover include guards with Blink style.
3055 r'\w+_h',
3056
3057 # Anything including the uppercase name of the file.
3058 r'\w*' + input_api.re.escape(replace_special_with_underscore(
3059 upper_base_file_name)) + r'\w*',
3060 ]
3061 guard_name_pattern = '|'.join(guard_name_pattern_list)
3062 guard_pattern = input_api.re.compile(
3063 r'#ifndef\s+(' + guard_name_pattern + ')')
3064
3065 for line_number, line in enumerate(f.NewContents()):
3066 if 'no-include-guard-because-multiply-included' in line:
3067 guard_name = 'DUMMY' # To not trigger check outside the loop.
3068 break
3069
3070 if guard_name is None:
3071 match = guard_pattern.match(line)
3072 if match:
3073 guard_name = match.group(1)
3074 guard_line_number = line_number
3075
3076 # We allow existing files to use slightly wrong include
3077 # guards, but new files should get it right.
3078 if not f.OldContents():
3079 is_in_blink = file_with_path.startswith(input_api.os_path.join(
3080 'third_party', 'WebKit'))
3081 if not (guard_name == expected_guard or
3082 is_in_blink and guard_name == expected_guard_if_blink):
3083 if is_in_blink:
3084 expected_text = "%s or %s" % (expected_guard,
3085 expected_guard_if_blink)
3086 else:
3087 expected_text = expected_guard
3088 errors.append(output_api.PresubmitPromptWarning(
3089 'Header using the wrong include guard name %s' % guard_name,
3090 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Daniel Bratell00e1b9bc2018-03-12 13:11:123091 'Expected: %r\nFound: %r' % (expected_text, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:143092 else:
3093 # The line after #ifndef should have a #define of the same name.
3094 if line_number == guard_line_number + 1:
3095 expected_line = '#define %s' % guard_name
3096 if line != expected_line:
3097 errors.append(output_api.PresubmitPromptWarning(
3098 'Missing "%s" for include guard' % expected_line,
3099 ['%s:%d' % (f.LocalPath(), line_number + 1)],
3100 'Expected: %r\nGot: %r' % (expected_line, line)))
3101
3102 if not seen_guard_end and line == '#endif // %s' % guard_name:
3103 seen_guard_end = True
3104 elif seen_guard_end:
3105 if line.strip() != '':
3106 errors.append(output_api.PresubmitPromptWarning(
3107 'Include guard %s not covering the whole file' % (
3108 guard_name), [f.LocalPath()]))
3109 break # Nothing else to check and enough to warn once.
3110
3111 if guard_name is None:
3112 errors.append(output_api.PresubmitPromptWarning(
3113 'Missing include guard %s' % expected_guard,
3114 [f.LocalPath()],
3115 'Missing include guard in %s\n'
3116 'Recommended name: %s\n'
3117 'This check can be disabled by having the string\n'
3118 'no-include-guard-because-multiply-included in the header.' %
3119 (f.LocalPath(), expected_guard)))
3120
3121 return errors
3122
3123
mostynbb639aca52015-01-07 20:31:233124def _CheckForWindowsLineEndings(input_api, output_api):
3125 """Check source code and known ascii text files for Windows style line
3126 endings.
3127 """
earthdok1b5e0ee2015-03-10 15:19:103128 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:233129
3130 file_inclusion_pattern = (
3131 known_text_files,
3132 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3133 )
3134
mostynbb639aca52015-01-07 20:31:233135 problems = []
Andrew Grieve933d12e2017-10-30 20:22:533136 source_file_filter = lambda f: input_api.FilterSourceFile(
3137 f, white_list=file_inclusion_pattern, black_list=None)
3138 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:503139 include_file = False
3140 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:233141 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:503142 include_file = True
3143 if include_file:
3144 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:233145
3146 if problems:
3147 return [output_api.PresubmitPromptWarning('Are you sure that you want '
3148 'these files to contain Windows style line endings?\n' +
3149 '\n'.join(problems))]
3150
3151 return []
3152
3153
Vaclav Brozekd5de76a2018-03-17 07:57:503154def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:133155 """Checks that all source files use SYSLOG properly."""
3156 syslog_files = []
3157 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:563158 for line_number, line in f.ChangedContents():
3159 if 'SYSLOG' in line:
3160 syslog_files.append(f.LocalPath() + ':' + str(line_number))
3161
pastarmovj89f7ee12016-09-20 14:58:133162 if syslog_files:
3163 return [output_api.PresubmitPromptWarning(
3164 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
3165 ' calls.\nFiles to check:\n', items=syslog_files)]
3166 return []
3167
3168
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193169def _CheckCrbugLinksHaveHttps(input_api, output_api):
Miguel Casas68bdb652017-12-19 16:29:093170 """Checks that crbug(.com) links are correctly prefixed by https://,
3171 unless they come in the accepted form TODO(crbug.com/...)
3172 """
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193173 white_list = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3174 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS)
3175 sources = lambda f: input_api.FilterSourceFile(
3176 f, white_list=white_list, black_list=black_list)
3177
3178 pattern = input_api.re.compile(r'//.*(?<!:\/\/)crbug[.com]*')
Miguel Casas68bdb652017-12-19 16:29:093179 accepted_pattern = input_api.re.compile(r'//.*TODO\(crbug[.com]*');
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193180 problems = []
3181 for f in input_api.AffectedSourceFiles(sources):
3182 for line_num, line in f.ChangedContents():
Miguel Casas68bdb652017-12-19 16:29:093183 if pattern.search(line) and not accepted_pattern.search(line):
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193184 problems.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
3185
3186 if problems:
3187 return [output_api.PresubmitPromptWarning(
3188 'Found unprefixed crbug.com URL(s), consider prepending https://\n'+
3189 '\n'.join(problems))]
3190 return []
3191
3192
[email protected]1f7b4172010-01-28 01:17:343193def CheckChangeOnUpload(input_api, output_api):
3194 results = []
3195 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:473196 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:283197 results.extend(
jam93a6ee792017-02-08 23:59:223198 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:193199 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:223200 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:133201 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:163202 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193203 results.extend(_CheckCrbugLinksHaveHttps(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:533204 results.extend(_CheckUniquePtr(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543205 return results
[email protected]ca8d1982009-02-19 16:33:123206
3207
[email protected]1bfb8322014-04-23 01:02:413208def GetTryServerMasterForBot(bot):
3209 """Returns the Try Server master for the given bot.
3210
[email protected]0bb112362014-07-26 04:38:323211 It tries to guess the master from the bot name, but may still fail
3212 and return None. There is no longer a default master.
3213 """
3214 # Potentially ambiguous bot names are listed explicitly.
3215 master_map = {
tandriie5587792016-07-14 00:34:503216 'chromium_presubmit': 'master.tryserver.chromium.linux',
3217 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:413218 }
[email protected]0bb112362014-07-26 04:38:323219 master = master_map.get(bot)
3220 if not master:
wnwen4fbaab82016-05-25 12:54:363221 if 'android' in bot:
tandriie5587792016-07-14 00:34:503222 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:363223 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:503224 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:323225 elif 'win' in bot:
tandriie5587792016-07-14 00:34:503226 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:323227 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:503228 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:323229 return master
[email protected]1bfb8322014-04-23 01:02:413230
3231
[email protected]ca8d1982009-02-19 16:33:123232def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:543233 results = []
[email protected]1f7b4172010-01-28 01:17:343234 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543235 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:273236 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:343237 input_api,
3238 output_api,
[email protected]2fdd1f362013-01-16 03:56:033239 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:273240
jam93a6ee792017-02-08 23:59:223241 results.extend(
3242 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:543243 results.extend(input_api.canned_checks.CheckChangeHasBugField(
3244 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:413245 results.extend(input_api.canned_checks.CheckChangeHasDescription(
3246 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543247 return results