blob: 390701ebeb76ddc0a4bfb56c1a3f4f5cbde4244a [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 (
Gabriel Charette7cc6c432018-04-25 20:52:02345 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59346 (
347 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
348 ),
349 False,
350 (),
351 ),
352 (
Gabriel Charette7cc6c432018-04-25 20:52:02353 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59354 (
355 'Consider using THREAD_CHECKER macros instead of the class directly.',
356 ),
357 False,
358 (),
359 ),
dbeamb6f4fde2017-06-15 04:03:06360 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06361 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
362 (
363 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
364 'deprecated (http://crbug.com/634507). Please avoid converting away',
365 'from the Time types in Chromium code, especially if any math is',
366 'being done on time values. For interfacing with platform/library',
367 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
368 'type converter methods instead. For faking TimeXXX values (for unit',
369 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
370 'other use cases, please contact base/time/OWNERS.',
371 ),
372 False,
373 (),
374 ),
375 (
dbeamb6f4fde2017-06-15 04:03:06376 'CallJavascriptFunctionUnsafe',
377 (
378 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
379 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
380 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
381 ),
382 False,
383 (
384 r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$',
385 r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$',
386 r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$',
387 ),
388 ),
dskiba1474c2bfd62017-07-20 02:19:24389 (
390 'leveldb::DB::Open',
391 (
392 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
393 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
394 "Chrome's tracing, making their memory usage visible.",
395 ),
396 True,
397 (
398 r'^third_party/leveldatabase/.*\.(cc|h)$',
399 ),
Gabriel Charette0592c3a2017-07-26 12:02:04400 ),
401 (
Chris Mumfordc38afb62017-10-09 17:55:08402 'leveldb::NewMemEnv',
403 (
404 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58405 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
406 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08407 ),
408 True,
409 (
410 r'^third_party/leveldatabase/.*\.(cc|h)$',
411 ),
412 ),
413 (
Gabriel Charetted9839bc2017-07-29 14:17:47414 'RunLoop::QuitCurrent',
415 (
Robert Liao64b7ab22017-08-04 23:03:43416 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
417 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47418 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41419 False,
Gabriel Charetted9839bc2017-07-29 14:17:47420 (),
Gabriel Charettea44975052017-08-21 23:14:04421 ),
422 (
423 'base::ScopedMockTimeMessageLoopTaskRunner',
424 (
Gabriel Charette87cc1af2018-04-25 20:52:51425 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
426 'ScopedTaskEnvironment::MainThreadType::MOCK_TIME. There are still a',
427 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
428 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
429 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04430 ),
Gabriel Charette87cc1af2018-04-25 20:52:51431 False,
Gabriel Charettea44975052017-08-21 23:14:04432 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57433 ),
434 (
435 r'std::regex',
436 (
437 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02438 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57439 ),
440 True,
441 (),
Francois Doray43670e32017-09-27 12:40:38442 ),
443 (
444 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
445 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
446 (
447 'Use the new API in base/threading/thread_restrictions.h.',
448 ),
449 True,
450 (),
451 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38452 (
453 r'/\bbase::Bind\(',
454 (
Gabriel Charette147335ea2018-03-22 15:59:19455 'Please consider using base::Bind{Once,Repeating} instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02456 'of base::Bind. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38457 ),
458 False,
459 (),
460 ),
461 (
462 r'/\bbase::Callback<',
463 (
Gabriel Charette147335ea2018-03-22 15:59:19464 'Please consider using base::{Once,Repeating}Callback instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02465 'of base::Callback. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38466 ),
467 False,
468 (),
469 ),
470 (
471 r'/\bbase::Closure\b',
472 (
Gabriel Charette147335ea2018-03-22 15:59:19473 'Please consider using base::{Once,Repeating}Closure instead',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02474 'of base::Closure. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38475 ),
476 False,
477 (),
478 ),
Victor Costan3653df62018-02-08 21:38:16479 (
Gabriel Charette147335ea2018-03-22 15:59:19480 r'RunMessageLoop',
481 (
482 'RunMessageLoop is deprecated, use RunLoop instead.',
483 ),
484 False,
485 (),
486 ),
487 (
488 r'RunThisRunLoop',
489 (
490 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
491 ),
492 False,
493 (),
494 ),
495 (
496 r'RunAllPendingInMessageLoop()',
497 (
498 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
499 "if you're convinced you need this.",
500 ),
501 False,
502 (),
503 ),
504 (
505 r'RunAllPendingInMessageLoop(BrowserThread',
506 (
507 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
508 'BrowserThread::UI, TestBrowserThreadBundle::RunIOThreadUntilIdle',
509 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
510 'async events instead of flushing threads.',
511 ),
512 False,
513 (),
514 ),
515 (
516 r'MessageLoopRunner',
517 (
518 'MessageLoopRunner is deprecated, use RunLoop instead.',
519 ),
520 False,
521 (),
522 ),
523 (
524 r'GetDeferredQuitTaskForRunLoop',
525 (
526 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
527 "gab@ if you found a use case where this is the only solution.",
528 ),
529 False,
530 (),
531 ),
532 (
Victor Costan3653df62018-02-08 21:38:16533 'sqlite3_initialize',
534 (
535 'Instead of sqlite3_initialize, depend on //sql, ',
536 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
537 ),
538 True,
539 (
540 r'^sql/initialization\.(cc|h)$',
541 r'^third_party/sqlite/.*\.(c|cc|h)$',
542 ),
543 ),
Matt Menke7f520a82018-03-28 21:38:37544 (
545 'net::URLFetcher',
546 (
547 'net::URLFetcher should no longer be used in content embedders. ',
548 'Instead, use network::SimpleURLLoader instead, which supports ',
549 'an out-of-process network stack. ',
550 'net::URLFetcher may still be used in binaries that do not embed',
551 'content.',
552 ),
Matt Menke59716d02018-04-05 12:45:53553 False,
Matt Menke7f520a82018-03-28 21:38:37554 (
555 r'^ios[\\\/].*\.(cc|h)$',
556 r'.*[\\\/]ios[\\\/].*\.(cc|h)$',
557 r'.*_ios\.(cc|h)$',
558 r'^net[\\\/].*\.(cc|h)$',
559 r'.*[\\\/]tools[\\\/].*\.(cc|h)$',
560 ),
561 ),
jdoerried7d10ab2018-04-27 10:46:13562 (
563 r'/\barraysize\b',
564 (
565 "arraysize is deprecated, please use base::size(array) instead ",
566 "(https://crbug.com/837308). ",
567 ),
568 False,
569 (),
570 ),
tzik5de2157f2018-05-08 03:42:47571 (
572 r'std::random_shuffle',
573 (
574 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
575 'base::RandomShuffle instead.'
576 ),
577 True,
578 (),
579 ),
[email protected]127f18ec2012-06-16 05:05:59580)
581
wnwenbdc444e2016-05-25 13:44:15582
mlamouria82272622014-09-16 18:45:04583_IPC_ENUM_TRAITS_DEPRECATED = (
584 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50585 'See http://www.chromium.org/Home/chromium-security/education/'
586 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:04587
Stephen Martinis97a394142018-06-07 23:06:05588_LONG_PATH_ERROR = (
589 'Some files included in this CL have file names that are too long (> 200'
590 ' characters). If committed, these files will cause issues on Windows. See'
591 ' https://crbug.com/612667 for more details.'
592)
593
Shenghua Zhangbfaa38b82017-11-16 21:58:02594_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
595 r".*[\\\/]BuildHooksAndroidImpl\.java",
James Wallace-Lee524eb682018-05-10 01:36:35596 r".*[\\\/]ClassRegisterImpl\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:02597 r".*[\\\/]LicenseContentProvider\.java",
James Wallace-Leef31ae6c2018-05-01 23:30:20598 r".*[\\\/]PlatformServiceBridgeImpl.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:02599]
[email protected]127f18ec2012-06-16 05:05:59600
Sean Kau46e29bc2017-08-28 16:31:16601# These paths contain test data and other known invalid JSON files.
602_KNOWN_INVALID_JSON_FILE_PATTERNS = [
603 r'test[\\\/]data[\\\/]',
604 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
605 r'^third_party[\\\/]protobuf[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16606 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Alexey Kozyatinskiya42a629f2018-04-17 17:49:38607 r'^third_party[\\\/]blink[\\\/]renderer[\\\/]devtools[\\\/]protocol\.json$',
Sean Kau46e29bc2017-08-28 16:31:16608]
609
610
[email protected]b00342e7f2013-03-26 16:21:54611_VALID_OS_MACROS = (
612 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08613 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54614 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:12615 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:54616 'OS_BSD',
617 'OS_CAT', # For testing.
618 'OS_CHROMEOS',
619 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37620 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54621 'OS_IOS',
622 'OS_LINUX',
623 'OS_MACOSX',
624 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21625 'OS_NACL_NONSFI',
626 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12627 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54628 'OS_OPENBSD',
629 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37630 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54631 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54632 'OS_WIN',
633)
634
635
agrievef32bcc72016-04-04 14:57:40636_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Grievea7f1ee902018-05-18 16:17:22637 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:40638 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04639 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58640 'build/secondary/third_party/android_platform/'
641 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19642 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40643]
644
wnwenbdc444e2016-05-25 13:44:15645
agrievef32bcc72016-04-04 14:57:40646_GENERIC_PYDEPS_FILES = [
John Chencde89192018-01-27 21:18:40647 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:22648 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:40649]
650
wnwenbdc444e2016-05-25 13:44:15651
agrievef32bcc72016-04-04 14:57:40652_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
653
654
Eric Boren6fd2b932018-01-25 15:05:08655# Bypass the AUTHORS check for these accounts.
656_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:29657 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
658 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
Eric Boren36af476a2018-06-08 16:21:08659 'fuchsia-sdk', 'nacl', 'pdfium', 'perfetto', 'skia',
660 'src-internal', 'webrtc')
Chan52654f52018-03-21 21:02:29661 ) | set('%[email protected]' % s for s in ('findit-for-me',))
Eric Boren6fd2b932018-01-25 15:05:08662
663
[email protected]55459852011-08-10 15:17:19664def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
665 """Attempts to prevent use of functions intended only for testing in
666 non-testing code. For now this is just a best-effort implementation
667 that ignores header files and may have some false positives. A
668 better implementation would probably need a proper C++ parser.
669 """
670 # We only scan .cc files and the like, as the declaration of
671 # for-testing functions in header files are hard to distinguish from
672 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44673 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19674
jochenc0d4808c2015-07-27 09:25:42675 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19676 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09677 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19678 exclusion_pattern = input_api.re.compile(
679 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
680 base_function_pattern, base_function_pattern))
681
682 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44683 black_list = (_EXCLUDED_PATHS +
684 _TEST_CODE_EXCLUDED_PATHS +
685 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19686 return input_api.FilterSourceFile(
687 affected_file,
688 white_list=(file_inclusion_pattern, ),
689 black_list=black_list)
690
691 problems = []
692 for f in input_api.AffectedSourceFiles(FilterFile):
693 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24694 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03695 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46696 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03697 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19698 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03699 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19700
701 if problems:
[email protected]f7051d52013-04-02 18:31:42702 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03703 else:
704 return []
[email protected]55459852011-08-10 15:17:19705
706
Vaclav Brozek7dbc28c2018-03-27 08:35:23707def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
708 """This is a simplified version of
709 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
710 """
711 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
712 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
713 name_pattern = r'ForTest(s|ing)?'
714 # Describes an occurrence of "ForTest*" inside a // comment.
715 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
716 # Catch calls.
717 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
718 # Ignore definitions. (Comments are ignored separately.)
719 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
720
721 problems = []
722 sources = lambda x: input_api.FilterSourceFile(
723 x,
724 black_list=(('(?i).*test', r'.*\/junit\/')
725 + input_api.DEFAULT_BLACK_LIST),
726 white_list=(r'.*\.java$',)
727 )
728 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
729 local_path = f.LocalPath()
730 is_inside_javadoc = False
731 for line_number, line in f.ChangedContents():
732 if is_inside_javadoc and javadoc_end_re.search(line):
733 is_inside_javadoc = False
734 if not is_inside_javadoc and javadoc_start_re.search(line):
735 is_inside_javadoc = True
736 if is_inside_javadoc:
737 continue
738 if (inclusion_re.search(line) and
739 not comment_re.search(line) and
740 not exclusion_re.search(line)):
741 problems.append(
742 '%s:%d\n %s' % (local_path, line_number, line.strip()))
743
744 if problems:
745 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
746 else:
747 return []
748
749
[email protected]10689ca2011-09-02 02:31:54750def _CheckNoIOStreamInHeaders(input_api, output_api):
751 """Checks to make sure no .h files include <iostream>."""
752 files = []
753 pattern = input_api.re.compile(r'^#include\s*<iostream>',
754 input_api.re.MULTILINE)
755 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
756 if not f.LocalPath().endswith('.h'):
757 continue
758 contents = input_api.ReadFile(f)
759 if pattern.search(contents):
760 files.append(f)
761
762 if len(files):
yolandyandaabc6d2016-04-18 18:29:39763 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06764 'Do not #include <iostream> in header files, since it inserts static '
765 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54766 '#include <ostream>. See http://crbug.com/94794',
767 files) ]
768 return []
769
770
[email protected]72df4e782012-06-21 16:28:18771def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52772 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18773 problems = []
774 for f in input_api.AffectedFiles():
775 if (not f.LocalPath().endswith(('.cc', '.mm'))):
776 continue
777
778 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04779 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18780 problems.append(' %s:%d' % (f.LocalPath(), line_num))
781
782 if not problems:
783 return []
784 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
785 '\n'.join(problems))]
786
787
danakj61c1aa22015-10-26 19:55:52788def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57789 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52790 errors = []
791 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
792 input_api.re.MULTILINE)
793 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
794 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
795 continue
796 for lnum, line in f.ChangedContents():
797 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17798 errors.append(output_api.PresubmitError(
799 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57800 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17801 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52802 return errors
803
804
mcasasb7440c282015-02-04 14:52:19805def _FindHistogramNameInLine(histogram_name, line):
806 """Tries to find a histogram name or prefix in a line."""
807 if not "affected-histogram" in line:
808 return histogram_name in line
809 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
810 # the histogram_name.
811 if not '"' in line:
812 return False
813 histogram_prefix = line.split('\"')[1]
814 return histogram_prefix in histogram_name
815
816
817def _CheckUmaHistogramChanges(input_api, output_api):
818 """Check that UMA histogram names in touched lines can still be found in other
819 lines of the patch or in histograms.xml. Note that this check would not catch
820 the reverse: changes in histograms.xml not matched in the code itself."""
821 touched_histograms = []
822 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:47823 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
824 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
825 name_pattern = r'"(.*?)"'
826 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
827 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
828 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
829 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
830 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:17831 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:19832 for f in input_api.AffectedFiles():
833 # If histograms.xml itself is modified, keep the modified lines for later.
834 if f.LocalPath().endswith(('histograms.xml')):
835 histograms_xml_modifications = f.ChangedContents()
836 continue
Vaclav Brozekbdac817c2018-03-24 06:30:47837 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
838 single_line_re = single_line_c_re
839 split_line_prefix_re = split_line_c_prefix_re
840 elif f.LocalPath().endswith(('java')):
841 single_line_re = single_line_java_re
842 split_line_prefix_re = split_line_java_prefix_re
843 else:
mcasasb7440c282015-02-04 14:52:19844 continue
845 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:17846 if last_line_matched_prefix:
847 suffix_found = split_line_suffix_re.search(line)
848 if suffix_found :
849 touched_histograms.append([suffix_found.group(1), f, line_num])
850 last_line_matched_prefix = False
851 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:06852 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:19853 if found:
854 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:17855 continue
856 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:19857
858 # Search for the touched histogram names in the local modifications to
859 # histograms.xml, and, if not found, on the base histograms.xml file.
860 unmatched_histograms = []
861 for histogram_info in touched_histograms:
862 histogram_name_found = False
863 for line_num, line in histograms_xml_modifications:
864 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
865 if histogram_name_found:
866 break
867 if not histogram_name_found:
868 unmatched_histograms.append(histogram_info)
869
eromanb90c82e7e32015-04-01 15:13:49870 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19871 problems = []
872 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49873 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19874 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45875 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19876 histogram_name_found = False
877 for line in histograms_xml:
878 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
879 if histogram_name_found:
880 break
881 if not histogram_name_found:
882 problems.append(' [%s:%d] %s' %
883 (f.LocalPath(), line_num, histogram_name))
884
885 if not problems:
886 return []
887 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
888 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49889 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19890
wnwenbdc444e2016-05-25 13:44:15891
yolandyandaabc6d2016-04-18 18:29:39892def _CheckFlakyTestUsage(input_api, output_api):
893 """Check that FlakyTest annotation is our own instead of the android one"""
894 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
895 files = []
896 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
897 if f.LocalPath().endswith('Test.java'):
898 if pattern.search(input_api.ReadFile(f)):
899 files.append(f)
900 if len(files):
901 return [output_api.PresubmitError(
902 'Use org.chromium.base.test.util.FlakyTest instead of '
903 'android.test.FlakyTest',
904 files)]
905 return []
mcasasb7440c282015-02-04 14:52:19906
wnwenbdc444e2016-05-25 13:44:15907
[email protected]8ea5d4b2011-09-13 21:49:22908def _CheckNoNewWStrings(input_api, output_api):
909 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27910 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22911 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20912 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57913 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34914 '/win/' in f.LocalPath() or
915 'chrome_elf' in f.LocalPath() or
916 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20917 continue
[email protected]8ea5d4b2011-09-13 21:49:22918
[email protected]a11dbe9b2012-08-07 01:32:58919 allowWString = False
[email protected]b5c24292011-11-28 14:38:20920 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58921 if 'presubmit: allow wstring' in line:
922 allowWString = True
923 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27924 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58925 allowWString = False
926 else:
927 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22928
[email protected]55463aa62011-10-12 00:48:27929 if not problems:
930 return []
931 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58932 ' If you are calling a cross-platform API that accepts a wstring, '
933 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27934 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22935
936
[email protected]2a8ac9c2011-10-19 17:20:44937def _CheckNoDEPSGIT(input_api, output_api):
938 """Make sure .DEPS.git is never modified manually."""
939 if any(f.LocalPath().endswith('.DEPS.git') for f in
940 input_api.AffectedFiles()):
941 return [output_api.PresubmitError(
942 'Never commit changes to .DEPS.git. This file is maintained by an\n'
943 'automated system based on what\'s in DEPS and your changes will be\n'
944 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50945 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
946 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:44947 'for more information')]
948 return []
949
950
tandriief664692014-09-23 14:51:47951def _CheckValidHostsInDEPS(input_api, output_api):
952 """Checks that DEPS file deps are from allowed_hosts."""
953 # Run only if DEPS file has been modified to annoy fewer bystanders.
954 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
955 return []
956 # Outsource work to gclient verify
957 try:
958 input_api.subprocess.check_output(['gclient', 'verify'])
959 return []
960 except input_api.subprocess.CalledProcessError, error:
961 return [output_api.PresubmitError(
962 'DEPS file must have only git dependencies.',
963 long_text=error.output)]
964
965
[email protected]127f18ec2012-06-16 05:05:59966def _CheckNoBannedFunctions(input_api, output_api):
967 """Make sure that banned functions are not used."""
968 warnings = []
969 errors = []
970
wnwenbdc444e2016-05-25 13:44:15971 def IsBlacklisted(affected_file, blacklist):
972 local_path = affected_file.LocalPath()
973 for item in blacklist:
974 if input_api.re.match(item, local_path):
975 return True
976 return False
977
Sylvain Defresnea8b73d252018-02-28 15:45:54978 def IsIosObcjFile(affected_file):
979 local_path = affected_file.LocalPath()
980 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
981 return False
982 basename = input_api.os_path.basename(local_path)
983 if 'ios' in basename.split('_'):
984 return True
985 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
986 if sep and 'ios' in local_path.split(sep):
987 return True
988 return False
989
wnwenbdc444e2016-05-25 13:44:15990 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
991 matched = False
992 if func_name[0:1] == '/':
993 regex = func_name[1:]
994 if input_api.re.search(regex, line):
995 matched = True
996 elif func_name in line:
dchenge07de812016-06-20 19:27:17997 matched = True
wnwenbdc444e2016-05-25 13:44:15998 if matched:
dchenge07de812016-06-20 19:27:17999 problems = warnings
wnwenbdc444e2016-05-25 13:44:151000 if error:
dchenge07de812016-06-20 19:27:171001 problems = errors
wnwenbdc444e2016-05-25 13:44:151002 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
1003 for message_line in message:
1004 problems.append(' %s' % message_line)
1005
Eric Stevensona9a980972017-09-23 00:04:411006 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1007 for f in input_api.AffectedFiles(file_filter=file_filter):
1008 for line_num, line in f.ChangedContents():
1009 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1010 CheckForMatch(f, line_num, line, func_name, message, error)
1011
[email protected]127f18ec2012-06-16 05:05:591012 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1013 for f in input_api.AffectedFiles(file_filter=file_filter):
1014 for line_num, line in f.ChangedContents():
1015 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151016 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591017
Sylvain Defresnea8b73d252018-02-28 15:45:541018 for f in input_api.AffectedFiles(file_filter=IsIosObcjFile):
1019 for line_num, line in f.ChangedContents():
1020 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1021 CheckForMatch(f, line_num, line, func_name, message, error)
1022
[email protected]127f18ec2012-06-16 05:05:591023 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1024 for f in input_api.AffectedFiles(file_filter=file_filter):
1025 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491026 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491027 if IsBlacklisted(f, excluded_paths):
1028 continue
wnwenbdc444e2016-05-25 13:44:151029 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591030
1031 result = []
1032 if (warnings):
1033 result.append(output_api.PresubmitPromptWarning(
1034 'Banned functions were used.\n' + '\n'.join(warnings)))
1035 if (errors):
1036 result.append(output_api.PresubmitError(
1037 'Banned functions were used.\n' + '\n'.join(errors)))
1038 return result
1039
1040
[email protected]6c063c62012-07-11 19:11:061041def _CheckNoPragmaOnce(input_api, output_api):
1042 """Make sure that banned functions are not used."""
1043 files = []
1044 pattern = input_api.re.compile(r'^#pragma\s+once',
1045 input_api.re.MULTILINE)
1046 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1047 if not f.LocalPath().endswith('.h'):
1048 continue
1049 contents = input_api.ReadFile(f)
1050 if pattern.search(contents):
1051 files.append(f)
1052
1053 if files:
1054 return [output_api.PresubmitError(
1055 'Do not use #pragma once in header files.\n'
1056 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1057 files)]
1058 return []
1059
[email protected]127f18ec2012-06-16 05:05:591060
[email protected]e7479052012-09-19 00:26:121061def _CheckNoTrinaryTrueFalse(input_api, output_api):
1062 """Checks to make sure we don't introduce use of foo ? true : false."""
1063 problems = []
1064 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1065 for f in input_api.AffectedFiles():
1066 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1067 continue
1068
1069 for line_num, line in f.ChangedContents():
1070 if pattern.match(line):
1071 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1072
1073 if not problems:
1074 return []
1075 return [output_api.PresubmitPromptWarning(
1076 'Please consider avoiding the "? true : false" pattern if possible.\n' +
1077 '\n'.join(problems))]
1078
1079
[email protected]55f9f382012-07-31 11:02:181080def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:281081 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:181082 change. Breaking - rules is an error, breaking ! rules is a
1083 warning.
1084 """
mohan.reddyf21db962014-10-16 12:26:471085 import sys
[email protected]55f9f382012-07-31 11:02:181086 # We need to wait until we have an input_api object and use this
1087 # roundabout construct to import checkdeps because this file is
1088 # eval-ed and thus doesn't have __file__.
1089 original_sys_path = sys.path
1090 try:
1091 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:471092 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:181093 import checkdeps
1094 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:241095 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:281096 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:181097 from rules import Rule
1098 finally:
1099 # Restore sys.path to what it was before.
1100 sys.path = original_sys_path
1101
1102 added_includes = []
rhalavati08acd232017-04-03 07:23:281103 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:241104 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:181105 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:281106 if CppChecker.IsCppFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501107 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081108 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:281109 elif ProtoChecker.IsProtoFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501110 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081111 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:241112 elif JavaChecker.IsJavaFile(f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501113 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081114 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:181115
[email protected]26385172013-05-09 23:11:351116 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181117
1118 error_descriptions = []
1119 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:281120 error_subjects = set()
1121 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:181122 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
1123 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:081124 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181125 description_with_path = '%s\n %s' % (path, rule_description)
1126 if rule_type == Rule.DISALLOW:
1127 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281128 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:181129 else:
1130 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281131 warning_subjects.add("#includes")
1132
1133 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
1134 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:081135 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:281136 description_with_path = '%s\n %s' % (path, rule_description)
1137 if rule_type == Rule.DISALLOW:
1138 error_descriptions.append(description_with_path)
1139 error_subjects.add("imports")
1140 else:
1141 warning_descriptions.append(description_with_path)
1142 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:181143
Jinsuk Kim5a092672017-10-24 22:42:241144 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:021145 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:081146 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:241147 description_with_path = '%s\n %s' % (path, rule_description)
1148 if rule_type == Rule.DISALLOW:
1149 error_descriptions.append(description_with_path)
1150 error_subjects.add("imports")
1151 else:
1152 warning_descriptions.append(description_with_path)
1153 warning_subjects.add("imports")
1154
[email protected]55f9f382012-07-31 11:02:181155 results = []
1156 if error_descriptions:
1157 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:281158 'You added one or more %s that violate checkdeps rules.'
1159 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:181160 error_descriptions))
1161 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:421162 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:281163 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:181164 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:281165 '%s? See relevant DEPS file(s) for details and contacts.' %
1166 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:181167 warning_descriptions))
1168 return results
1169
1170
[email protected]fbcafe5a2012-08-08 15:31:221171def _CheckFilePermissions(input_api, output_api):
1172 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:151173 if input_api.platform == 'win32':
1174 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:291175 checkperms_tool = input_api.os_path.join(
1176 input_api.PresubmitLocalPath(),
1177 'tools', 'checkperms', 'checkperms.py')
1178 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:471179 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:391180 with input_api.CreateTemporaryFile() as file_list:
1181 for f in input_api.AffectedFiles():
1182 # checkperms.py file/directory arguments must be relative to the
1183 # repository.
1184 file_list.write(f.LocalPath() + '\n')
1185 file_list.close()
1186 args += ['--file-list', file_list.name]
1187 try:
1188 input_api.subprocess.check_output(args)
1189 return []
1190 except input_api.subprocess.CalledProcessError as error:
1191 return [output_api.PresubmitError(
1192 'checkperms.py failed:',
1193 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:221194
1195
robertocn832f5992017-01-04 19:01:301196def _CheckTeamTags(input_api, output_api):
1197 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
1198 checkteamtags_tool = input_api.os_path.join(
1199 input_api.PresubmitLocalPath(),
1200 'tools', 'checkteamtags', 'checkteamtags.py')
1201 args = [input_api.python_executable, checkteamtags_tool,
1202 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:221203 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:301204 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
1205 'OWNERS']
1206 try:
1207 if files:
1208 input_api.subprocess.check_output(args + files)
1209 return []
1210 except input_api.subprocess.CalledProcessError as error:
1211 return [output_api.PresubmitError(
1212 'checkteamtags.py failed:',
1213 long_text=error.output)]
1214
1215
[email protected]c8278b32012-10-30 20:35:491216def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
1217 """Makes sure we don't include ui/aura/window_property.h
1218 in header files.
1219 """
1220 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1221 errors = []
1222 for f in input_api.AffectedFiles():
1223 if not f.LocalPath().endswith('.h'):
1224 continue
1225 for line_num, line in f.ChangedContents():
1226 if pattern.match(line):
1227 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1228
1229 results = []
1230 if errors:
1231 results.append(output_api.PresubmitError(
1232 'Header files should not include ui/aura/window_property.h', errors))
1233 return results
1234
1235
[email protected]70ca77752012-11-20 03:45:031236def _CheckForVersionControlConflictsInFile(input_api, f):
1237 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1238 errors = []
1239 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231240 if f.LocalPath().endswith('.md'):
1241 # First-level headers in markdown look a lot like version control
1242 # conflict markers. http://daringfireball.net/projects/markdown/basics
1243 continue
[email protected]70ca77752012-11-20 03:45:031244 if pattern.match(line):
1245 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1246 return errors
1247
1248
1249def _CheckForVersionControlConflicts(input_api, output_api):
1250 """Usually this is not intentional and will cause a compile failure."""
1251 errors = []
1252 for f in input_api.AffectedFiles():
1253 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1254
1255 results = []
1256 if errors:
1257 results.append(output_api.PresubmitError(
1258 'Version control conflict markers found, please resolve.', errors))
1259 return results
1260
estadee17314a02017-01-12 16:22:161261def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1262 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1263 errors = []
1264 for f in input_api.AffectedFiles():
1265 for line_num, line in f.ChangedContents():
1266 if pattern.search(line):
1267 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1268
1269 results = []
1270 if errors:
1271 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:501272 'Found Google support URL addressed by answer number. Please replace '
1273 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:161274 return results
1275
[email protected]70ca77752012-11-20 03:45:031276
[email protected]06e6d0ff2012-12-11 01:36:441277def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1278 def FilterFile(affected_file):
1279 """Filter function for use with input_api.AffectedSourceFiles,
1280 below. This filters out everything except non-test files from
1281 top-level directories that generally speaking should not hard-code
1282 service URLs (e.g. src/android_webview/, src/content/ and others).
1283 """
1284 return input_api.FilterSourceFile(
1285 affected_file,
[email protected]78bb39d62012-12-11 15:11:561286 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441287 black_list=(_EXCLUDED_PATHS +
1288 _TEST_CODE_EXCLUDED_PATHS +
1289 input_api.DEFAULT_BLACK_LIST))
1290
reillyi38965732015-11-16 18:27:331291 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1292 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461293 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1294 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441295 problems = [] # items are (filename, line_number, line)
1296 for f in input_api.AffectedSourceFiles(FilterFile):
1297 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461298 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441299 problems.append((f.LocalPath(), line_num, line))
1300
1301 if problems:
[email protected]f7051d52013-04-02 18:31:421302 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441303 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581304 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441305 [' %s:%d: %s' % (
1306 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031307 else:
1308 return []
[email protected]06e6d0ff2012-12-11 01:36:441309
1310
[email protected]d2530012013-01-25 16:39:271311def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1312 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311313 The native_client_sdk directory is excluded because it has auto-generated PNG
1314 files for documentation.
[email protected]d2530012013-01-25 16:39:271315 """
[email protected]d2530012013-01-25 16:39:271316 errors = []
binji0dcdf342014-12-12 18:32:311317 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1318 black_list = (r'^native_client_sdk[\\\/]',)
1319 file_filter = lambda f: input_api.FilterSourceFile(
1320 f, white_list=white_list, black_list=black_list)
1321 for f in input_api.AffectedFiles(include_deletes=False,
1322 file_filter=file_filter):
1323 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271324
1325 results = []
1326 if errors:
1327 results.append(output_api.PresubmitError(
1328 'The name of PNG files should not have abbreviations. \n'
1329 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1330 'Contact [email protected] if you have questions.', errors))
1331 return results
1332
1333
Daniel Cheng4dcdb6b2017-04-13 08:30:171334def _ExtractAddRulesFromParsedDeps(parsed_deps):
1335 """Extract the rules that add dependencies from a parsed DEPS file.
1336
1337 Args:
1338 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1339 add_rules = set()
1340 add_rules.update([
1341 rule[1:] for rule in parsed_deps.get('include_rules', [])
1342 if rule.startswith('+') or rule.startswith('!')
1343 ])
Vaclav Brozekd5de76a2018-03-17 07:57:501344 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:171345 {}).iteritems():
1346 add_rules.update([
1347 rule[1:] for rule in rules
1348 if rule.startswith('+') or rule.startswith('!')
1349 ])
1350 return add_rules
1351
1352
1353def _ParseDeps(contents):
1354 """Simple helper for parsing DEPS files."""
1355 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171356 class _VarImpl:
1357
1358 def __init__(self, local_scope):
1359 self._local_scope = local_scope
1360
1361 def Lookup(self, var_name):
1362 """Implements the Var syntax."""
1363 try:
1364 return self._local_scope['vars'][var_name]
1365 except KeyError:
1366 raise Exception('Var is not defined: %s' % var_name)
1367
1368 local_scope = {}
1369 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171370 'Var': _VarImpl(local_scope).Lookup,
1371 }
1372 exec contents in global_scope, local_scope
1373 return local_scope
1374
1375
1376def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081377 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411378 a set of DEPS entries that we should look up.
1379
1380 For a directory (rather than a specific filename) we fake a path to
1381 a specific filename by adding /DEPS. This is chosen as a file that
1382 will seldom or never be subject to per-file include_rules.
1383 """
[email protected]2b438d62013-11-14 17:54:141384 # We ignore deps entries on auto-generated directories.
1385 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081386
Daniel Cheng4dcdb6b2017-04-13 08:30:171387 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1388 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1389
1390 added_deps = new_deps.difference(old_deps)
1391
[email protected]2b438d62013-11-14 17:54:141392 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171393 for added_dep in added_deps:
1394 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1395 continue
1396 # Assume that a rule that ends in .h is a rule for a specific file.
1397 if added_dep.endswith('.h'):
1398 results.add(added_dep)
1399 else:
1400 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081401 return results
1402
1403
[email protected]e871964c2013-05-13 14:14:551404def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1405 """When a dependency prefixed with + is added to a DEPS file, we
1406 want to make sure that the change is reviewed by an OWNER of the
1407 target file or directory, to avoid layering violations from being
1408 introduced. This check verifies that this happens.
1409 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171410 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241411
1412 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191413 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241414 for f in input_api.AffectedFiles(include_deletes=False,
1415 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551416 filename = input_api.os_path.basename(f.LocalPath())
1417 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171418 virtual_depended_on_files.update(_CalculateAddedDeps(
1419 input_api.os_path,
1420 '\n'.join(f.OldContents()),
1421 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551422
[email protected]e871964c2013-05-13 14:14:551423 if not virtual_depended_on_files:
1424 return []
1425
1426 if input_api.is_committing:
1427 if input_api.tbr:
1428 return [output_api.PresubmitNotifyResult(
1429 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271430 if input_api.dry_run:
1431 return [output_api.PresubmitNotifyResult(
1432 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551433 if not input_api.change.issue:
1434 return [output_api.PresubmitError(
1435 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401436 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551437 output = output_api.PresubmitError
1438 else:
1439 output = output_api.PresubmitNotifyResult
1440
1441 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501442 owner_email, reviewers = (
1443 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1444 input_api,
1445 owners_db.email_regexp,
1446 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551447
1448 owner_email = owner_email or input_api.change.author_email
1449
[email protected]de4f7d22013-05-23 14:27:461450 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511451 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461452 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551453 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1454 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411455
1456 # We strip the /DEPS part that was added by
1457 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1458 # directory.
1459 def StripDeps(path):
1460 start_deps = path.rfind('/DEPS')
1461 if start_deps != -1:
1462 return path[:start_deps]
1463 else:
1464 return path
1465 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551466 for path in missing_files]
1467
1468 if unapproved_dependencies:
1469 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151470 output('You need LGTM from owners of depends-on paths in DEPS that were '
1471 'modified in this CL:\n %s' %
1472 '\n '.join(sorted(unapproved_dependencies)))]
1473 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1474 output_list.append(output(
1475 'Suggested missing target path OWNERS:\n %s' %
1476 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551477 return output_list
1478
1479 return []
1480
1481
[email protected]85218562013-11-22 07:41:401482def _CheckSpamLogging(input_api, output_api):
1483 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1484 black_list = (_EXCLUDED_PATHS +
1485 _TEST_CODE_EXCLUDED_PATHS +
1486 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501487 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191488 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481489 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461490 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121491 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1492 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581493 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161494 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031495 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151496 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1497 r"^chromecast[\\\/]",
1498 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481499 r"^components[\\\/]browser_watcher[\\\/]"
1500 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311501 r"^components[\\\/]html_viewer[\\\/]"
1502 r"web_test_delegate_impl\.cc$",
Samuel Huang577ef6c2018-03-13 18:19:341503 r"^components[\\\/]zucchini[\\\/].*",
peter80739bb2015-10-20 11:17:461504 # TODO(peter): Remove this exception. https://crbug.com/534537
1505 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1506 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251507 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1508 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241509 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111510 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151511 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111512 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521513 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501514 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361515 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311516 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131517 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001518 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441519 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451520 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021521 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351522 r"dump_file_system.cc$",
1523 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401524 source_file_filter = lambda x: input_api.FilterSourceFile(
1525 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1526
thomasanderson625d3932017-03-29 07:16:581527 log_info = set([])
1528 printf = set([])
[email protected]85218562013-11-22 07:41:401529
1530 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581531 for _, line in f.ChangedContents():
1532 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1533 log_info.add(f.LocalPath())
1534 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1535 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371536
thomasanderson625d3932017-03-29 07:16:581537 if input_api.re.search(r"\bprintf\(", line):
1538 printf.add(f.LocalPath())
1539 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1540 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401541
1542 if log_info:
1543 return [output_api.PresubmitError(
1544 'These files spam the console log with LOG(INFO):',
1545 items=log_info)]
1546 if printf:
1547 return [output_api.PresubmitError(
1548 'These files spam the console log with printf/fprintf:',
1549 items=printf)]
1550 return []
1551
1552
[email protected]49aa76a2013-12-04 06:59:161553def _CheckForAnonymousVariables(input_api, output_api):
1554 """These types are all expected to hold locks while in scope and
1555 so should never be anonymous (which causes them to be immediately
1556 destroyed)."""
1557 they_who_must_be_named = [
1558 'base::AutoLock',
1559 'base::AutoReset',
1560 'base::AutoUnlock',
1561 'SkAutoAlphaRestore',
1562 'SkAutoBitmapShaderInstall',
1563 'SkAutoBlitterChoose',
1564 'SkAutoBounderCommit',
1565 'SkAutoCallProc',
1566 'SkAutoCanvasRestore',
1567 'SkAutoCommentBlock',
1568 'SkAutoDescriptor',
1569 'SkAutoDisableDirectionCheck',
1570 'SkAutoDisableOvalCheck',
1571 'SkAutoFree',
1572 'SkAutoGlyphCache',
1573 'SkAutoHDC',
1574 'SkAutoLockColors',
1575 'SkAutoLockPixels',
1576 'SkAutoMalloc',
1577 'SkAutoMaskFreeImage',
1578 'SkAutoMutexAcquire',
1579 'SkAutoPathBoundsUpdate',
1580 'SkAutoPDFRelease',
1581 'SkAutoRasterClipValidate',
1582 'SkAutoRef',
1583 'SkAutoTime',
1584 'SkAutoTrace',
1585 'SkAutoUnref',
1586 ]
1587 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1588 # bad: base::AutoLock(lock.get());
1589 # not bad: base::AutoLock lock(lock.get());
1590 bad_pattern = input_api.re.compile(anonymous)
1591 # good: new base::AutoLock(lock.get())
1592 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1593 errors = []
1594
1595 for f in input_api.AffectedFiles():
1596 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1597 continue
1598 for linenum, line in f.ChangedContents():
1599 if bad_pattern.search(line) and not good_pattern.search(line):
1600 errors.append('%s:%d' % (f.LocalPath(), linenum))
1601
1602 if errors:
1603 return [output_api.PresubmitError(
1604 'These lines create anonymous variables that need to be named:',
1605 items=errors)]
1606 return []
1607
1608
Peter Kasting4844e46e2018-02-23 07:27:101609def _CheckUniquePtr(input_api, output_api):
1610 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1611 sources = lambda affected_file: input_api.FilterSourceFile(
1612 affected_file,
1613 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1614 input_api.DEFAULT_BLACK_LIST),
1615 white_list=(file_inclusion_pattern,))
Vaclav Brozeka54c528b2018-04-06 19:23:551616
1617 # Pattern to capture a single "<...>" block of template arguments. It can
1618 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
1619 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
1620 # latter would likely require counting that < and > match, which is not
1621 # expressible in regular languages. Should the need arise, one can introduce
1622 # limited counting (matching up to a total number of nesting depth), which
1623 # should cover all practical cases for already a low nesting limit.
1624 template_arg_pattern = (
1625 r'<[^>]*' # Opening block of <.
1626 r'>([^<]*>)?') # Closing block of >.
1627 # Prefix expressing that whatever follows is not already inside a <...>
1628 # block.
1629 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:101630 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:551631 not_inside_template_arg_pattern
1632 + r'\bstd::unique_ptr'
1633 + template_arg_pattern
1634 + r'\(\)')
1635
1636 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
1637 template_arg_no_array_pattern = (
1638 r'<[^>]*[^]]' # Opening block of <.
1639 r'>([^(<]*[^]]>)?') # Closing block of >.
1640 # Prefix saying that what follows is the start of an expression.
1641 start_of_expr_pattern = r'(=|\breturn|^)\s*'
1642 # Suffix saying that what follows are call parentheses with a non-empty list
1643 # of arguments.
1644 nonempty_arg_list_pattern = r'\(([^)]|$)'
1645 return_construct_pattern = input_api.re.compile(
1646 start_of_expr_pattern
1647 + r'std::unique_ptr'
1648 + template_arg_no_array_pattern
1649 + nonempty_arg_list_pattern)
1650
Vaclav Brozek851d9602018-04-04 16:13:051651 problems_constructor = []
1652 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:101653 for f in input_api.AffectedSourceFiles(sources):
1654 for line_number, line in f.ChangedContents():
1655 # Disallow:
1656 # return std::unique_ptr<T>(foo);
1657 # bar = std::unique_ptr<T>(foo);
1658 # But allow:
1659 # return std::unique_ptr<T[]>(foo);
1660 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozek851d9602018-04-04 16:13:051661 local_path = f.LocalPath()
Peter Kasting4844e46e2018-02-23 07:27:101662 if return_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:051663 problems_constructor.append(
1664 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:101665 # Disallow:
1666 # std::unique_ptr<T>()
1667 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:051668 problems_nullptr.append(
1669 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1670
1671 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:161672 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:051673 errors.append(output_api.PresubmitError(
1674 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:161675 problems_nullptr))
1676 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:051677 errors.append(output_api.PresubmitError(
1678 'The following files use explicit std::unique_ptr constructor.'
1679 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:161680 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:101681 return errors
1682
1683
[email protected]999261d2014-03-03 20:08:081684def _CheckUserActionUpdate(input_api, output_api):
1685 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521686 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081687 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521688 # If actions.xml is already included in the changelist, the PRESUBMIT
1689 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081690 return []
1691
[email protected]999261d2014-03-03 20:08:081692 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1693 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521694 current_actions = None
[email protected]999261d2014-03-03 20:08:081695 for f in input_api.AffectedFiles(file_filter=file_filter):
1696 for line_num, line in f.ChangedContents():
1697 match = input_api.re.search(action_re, line)
1698 if match:
[email protected]2f92dec2014-03-07 19:21:521699 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1700 # loaded only once.
1701 if not current_actions:
1702 with open('tools/metrics/actions/actions.xml') as actions_f:
1703 current_actions = actions_f.read()
1704 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081705 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521706 action = 'name="{0}"'.format(action_name)
1707 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081708 return [output_api.PresubmitPromptWarning(
1709 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521710 'tools/metrics/actions/actions.xml. Please run '
1711 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081712 % (f.LocalPath(), line_num, action_name))]
1713 return []
1714
1715
Daniel Cheng13ca61a882017-08-25 15:11:251716def _ImportJSONCommentEater(input_api):
1717 import sys
1718 sys.path = sys.path + [input_api.os_path.join(
1719 input_api.PresubmitLocalPath(),
1720 'tools', 'json_comment_eater')]
1721 import json_comment_eater
1722 return json_comment_eater
1723
1724
[email protected]99171a92014-06-03 08:44:471725def _GetJSONParseError(input_api, filename, eat_comments=True):
1726 try:
1727 contents = input_api.ReadFile(filename)
1728 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251729 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131730 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471731
1732 input_api.json.loads(contents)
1733 except ValueError as e:
1734 return e
1735 return None
1736
1737
1738def _GetIDLParseError(input_api, filename):
1739 try:
1740 contents = input_api.ReadFile(filename)
1741 idl_schema = input_api.os_path.join(
1742 input_api.PresubmitLocalPath(),
1743 'tools', 'json_schema_compiler', 'idl_schema.py')
1744 process = input_api.subprocess.Popen(
1745 [input_api.python_executable, idl_schema],
1746 stdin=input_api.subprocess.PIPE,
1747 stdout=input_api.subprocess.PIPE,
1748 stderr=input_api.subprocess.PIPE,
1749 universal_newlines=True)
1750 (_, error) = process.communicate(input=contents)
1751 return error or None
1752 except ValueError as e:
1753 return e
1754
1755
1756def _CheckParseErrors(input_api, output_api):
1757 """Check that IDL and JSON files do not contain syntax errors."""
1758 actions = {
1759 '.idl': _GetIDLParseError,
1760 '.json': _GetJSONParseError,
1761 }
[email protected]99171a92014-06-03 08:44:471762 # Most JSON files are preprocessed and support comments, but these do not.
1763 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491764 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471765 ]
1766 # Only run IDL checker on files in these directories.
1767 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491768 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1769 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471770 ]
1771
1772 def get_action(affected_file):
1773 filename = affected_file.LocalPath()
1774 return actions.get(input_api.os_path.splitext(filename)[1])
1775
[email protected]99171a92014-06-03 08:44:471776 def FilterFile(affected_file):
1777 action = get_action(affected_file)
1778 if not action:
1779 return False
1780 path = affected_file.LocalPath()
1781
Sean Kau46e29bc2017-08-28 16:31:161782 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471783 return False
1784
1785 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161786 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471787 return False
1788 return True
1789
1790 results = []
1791 for affected_file in input_api.AffectedFiles(
1792 file_filter=FilterFile, include_deletes=False):
1793 action = get_action(affected_file)
1794 kwargs = {}
1795 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161796 _MatchesFile(input_api, json_no_comments_patterns,
1797 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471798 kwargs['eat_comments'] = False
1799 parse_error = action(input_api,
1800 affected_file.AbsoluteLocalPath(),
1801 **kwargs)
1802 if parse_error:
1803 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1804 (affected_file.LocalPath(), parse_error)))
1805 return results
1806
1807
[email protected]760deea2013-12-10 19:33:491808def _CheckJavaStyle(input_api, output_api):
1809 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471810 import sys
[email protected]760deea2013-12-10 19:33:491811 original_sys_path = sys.path
1812 try:
1813 sys.path = sys.path + [input_api.os_path.join(
1814 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1815 import checkstyle
1816 finally:
1817 # Restore sys.path to what it was before.
1818 sys.path = original_sys_path
1819
1820 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091821 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511822 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491823
1824
Sean Kau46e29bc2017-08-28 16:31:161825def _MatchesFile(input_api, patterns, path):
1826 for pattern in patterns:
1827 if input_api.re.search(pattern, path):
1828 return True
1829 return False
1830
1831
Daniel Cheng7052cdf2017-11-21 19:23:291832def _GetOwnersFilesToCheckForIpcOwners(input_api):
1833 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:171834
Daniel Cheng7052cdf2017-11-21 19:23:291835 Returns:
1836 A dictionary mapping an OWNER file to the list of OWNERS rules it must
1837 contain to cover IPC-related files with noparent reviewer rules.
1838 """
1839 # Whether or not a file affects IPC is (mostly) determined by a simple list
1840 # of filename patterns.
dchenge07de812016-06-20 19:27:171841 file_patterns = [
palmerb19a0932017-01-24 04:00:311842 # Legacy IPC:
dchenge07de812016-06-20 19:27:171843 '*_messages.cc',
1844 '*_messages*.h',
1845 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311846 # Mojo IPC:
dchenge07de812016-06-20 19:27:171847 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:471848 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:171849 '*_struct_traits*.*',
1850 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311851 '*.typemap',
1852 # Android native IPC:
1853 '*.aidl',
1854 # Blink uses a different file naming convention:
1855 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:471856 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:171857 '*StructTraits*.*',
1858 '*TypeConverter*.*',
1859 ]
1860
scottmg7a6ed5ba2016-11-04 18:22:041861 # These third_party directories do not contain IPCs, but contain files
1862 # matching the above patterns, which trigger false positives.
1863 exclude_paths = [
1864 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291865 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041866 ]
1867
dchenge07de812016-06-20 19:27:171868 # Dictionary mapping an OWNERS file path to Patterns.
1869 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1870 # rules ) to a PatternEntry.
1871 # PatternEntry is a dictionary with two keys:
1872 # - 'files': the files that are matched by this pattern
1873 # - 'rules': the per-file rules needed for this pattern
1874 # For example, if we expect OWNERS file to contain rules for *.mojom and
1875 # *_struct_traits*.*, Patterns might look like this:
1876 # {
1877 # '*.mojom': {
1878 # 'files': ...,
1879 # 'rules': [
1880 # 'per-file *.mojom=set noparent',
1881 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1882 # ],
1883 # },
1884 # '*_struct_traits*.*': {
1885 # 'files': ...,
1886 # 'rules': [
1887 # 'per-file *_struct_traits*.*=set noparent',
1888 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1889 # ],
1890 # },
1891 # }
1892 to_check = {}
1893
Daniel Cheng13ca61a882017-08-25 15:11:251894 def AddPatternToCheck(input_file, pattern):
1895 owners_file = input_api.os_path.join(
1896 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1897 if owners_file not in to_check:
1898 to_check[owners_file] = {}
1899 if pattern not in to_check[owners_file]:
1900 to_check[owners_file][pattern] = {
1901 'files': [],
1902 'rules': [
1903 'per-file %s=set noparent' % pattern,
1904 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1905 ]
1906 }
Vaclav Brozekd5de76a2018-03-17 07:57:501907 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:251908
dchenge07de812016-06-20 19:27:171909 # Iterate through the affected files to see what we actually need to check
1910 # for. We should only nag patch authors about per-file rules if a file in that
1911 # directory would match that pattern. If a directory only contains *.mojom
1912 # files and no *_messages*.h files, we should only nag about rules for
1913 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251914 for f in input_api.AffectedFiles(include_deletes=False):
1915 # Manifest files don't have a strong naming convention. Instead, scan
1916 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161917 if (f.LocalPath().endswith('.json') and
1918 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1919 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251920 json_comment_eater = _ImportJSONCommentEater(input_api)
1921 mostly_json_lines = '\n'.join(f.NewContents())
1922 # Comments aren't allowed in strict JSON, so filter them out.
1923 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:431924 try:
1925 json_content = input_api.json.loads(json_lines)
1926 except:
1927 # There's another PRESUBMIT check that already verifies that JSON files
1928 # are not invalid, so no need to emit another warning here.
1929 continue
Daniel Cheng13ca61a882017-08-25 15:11:251930 if 'interface_provider_specs' in json_content:
1931 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171932 for pattern in file_patterns:
1933 if input_api.fnmatch.fnmatch(
1934 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041935 skip = False
1936 for exclude in exclude_paths:
1937 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1938 skip = True
1939 break
1940 if skip:
1941 continue
Daniel Cheng13ca61a882017-08-25 15:11:251942 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171943 break
1944
Daniel Cheng7052cdf2017-11-21 19:23:291945 return to_check
1946
1947
1948def _CheckIpcOwners(input_api, output_api):
1949 """Checks that affected files involving IPC have an IPC OWNERS rule."""
1950 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
1951
1952 if to_check:
1953 # If there are any OWNERS files to check, there are IPC-related changes in
1954 # this CL. Auto-CC the review list.
1955 output_api.AppendCC('[email protected]')
1956
1957 # Go through the OWNERS files to check, filtering out rules that are already
1958 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:171959 for owners_file, patterns in to_check.iteritems():
1960 try:
1961 with file(owners_file) as f:
1962 lines = set(f.read().splitlines())
1963 for entry in patterns.itervalues():
1964 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1965 ]
1966 except IOError:
1967 # No OWNERS file, so all the rules are definitely missing.
1968 continue
1969
1970 # All the remaining lines weren't found in OWNERS files, so emit an error.
1971 errors = []
1972 for owners_file, patterns in to_check.iteritems():
1973 missing_lines = []
1974 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:501975 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:171976 missing_lines.extend(entry['rules'])
1977 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1978 if missing_lines:
1979 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:051980 'Because of the presence of files:\n%s\n\n'
1981 '%s needs the following %d lines added:\n\n%s' %
1982 ('\n'.join(files), owners_file, len(missing_lines),
1983 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:171984
1985 results = []
1986 if errors:
vabrf5ce3bf92016-07-11 14:52:411987 if input_api.is_committing:
1988 output = output_api.PresubmitError
1989 else:
1990 output = output_api.PresubmitPromptWarning
1991 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591992 'Found OWNERS files that need to be updated for IPC security ' +
1993 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171994 long_text='\n\n'.join(errors)))
1995
1996 return results
1997
1998
jbriance9e12f162016-11-25 07:57:501999def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:312000 """Checks that added or removed lines in non third party affected
2001 header files do not lead to new useless class or struct forward
2002 declaration.
jbriance9e12f162016-11-25 07:57:502003 """
2004 results = []
2005 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
2006 input_api.re.MULTILINE)
2007 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
2008 input_api.re.MULTILINE)
2009 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:312010 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:192011 not f.LocalPath().startswith('third_party/blink') and
2012 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:312013 not f.LocalPath().startswith('third_party/WebKit') and
2014 not f.LocalPath().startswith('third_party\\WebKit')):
2015 continue
2016
jbriance9e12f162016-11-25 07:57:502017 if not f.LocalPath().endswith('.h'):
2018 continue
2019
2020 contents = input_api.ReadFile(f)
2021 fwd_decls = input_api.re.findall(class_pattern, contents)
2022 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
2023
2024 useless_fwd_decls = []
2025 for decl in fwd_decls:
2026 count = sum(1 for _ in input_api.re.finditer(
2027 r'\b%s\b' % input_api.re.escape(decl), contents))
2028 if count == 1:
2029 useless_fwd_decls.append(decl)
2030
2031 if not useless_fwd_decls:
2032 continue
2033
2034 for line in f.GenerateScmDiff().splitlines():
2035 if (line.startswith('-') and not line.startswith('--') or
2036 line.startswith('+') and not line.startswith('++')):
2037 for decl in useless_fwd_decls:
2038 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
2039 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:242040 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:502041 (f.LocalPath(), decl)))
2042 useless_fwd_decls.remove(decl)
2043
2044 return results
2045
2046
dskiba88634f4e2015-08-14 23:03:292047def _CheckAndroidToastUsage(input_api, output_api):
2048 """Checks that code uses org.chromium.ui.widget.Toast instead of
2049 android.widget.Toast (Chromium Toast doesn't force hardware
2050 acceleration on low-end devices, saving memory).
2051 """
2052 toast_import_pattern = input_api.re.compile(
2053 r'^import android\.widget\.Toast;$')
2054
2055 errors = []
2056
2057 sources = lambda affected_file: input_api.FilterSourceFile(
2058 affected_file,
2059 black_list=(_EXCLUDED_PATHS +
2060 _TEST_CODE_EXCLUDED_PATHS +
2061 input_api.DEFAULT_BLACK_LIST +
2062 (r'^chromecast[\\\/].*',
2063 r'^remoting[\\\/].*')),
2064 white_list=(r'.*\.java$',))
2065
2066 for f in input_api.AffectedSourceFiles(sources):
2067 for line_num, line in f.ChangedContents():
2068 if toast_import_pattern.search(line):
2069 errors.append("%s:%d" % (f.LocalPath(), line_num))
2070
2071 results = []
2072
2073 if errors:
2074 results.append(output_api.PresubmitError(
2075 'android.widget.Toast usage is detected. Android toasts use hardware'
2076 ' acceleration, and can be\ncostly on low-end devices. Please use'
2077 ' org.chromium.ui.widget.Toast instead.\n'
2078 'Contact [email protected] if you have any questions.',
2079 errors))
2080
2081 return results
2082
2083
dgnaa68d5e2015-06-10 10:08:222084def _CheckAndroidCrLogUsage(input_api, output_api):
2085 """Checks that new logs using org.chromium.base.Log:
2086 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:512087 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:222088 """
pkotwicza1dd0b002016-05-16 14:41:042089
torne89540622017-03-24 19:41:302090 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:042091 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:302092 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:042093 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:302094 # WebView license viewer code cannot depend on //base; used in stub APK.
2095 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
2096 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:042097 ]
2098
dgnaa68d5e2015-06-10 10:08:222099 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:122100 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
2101 class_in_base_pattern = input_api.re.compile(
2102 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
2103 has_some_log_import_pattern = input_api.re.compile(
2104 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222105 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:122106 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:222107 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:512108 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:222109 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222110
Vincent Scheib16d7b272015-09-15 18:09:072111 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:222112 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:042113 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
2114 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:122115
dgnaa68d5e2015-06-10 10:08:222116 tag_decl_errors = []
2117 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:122118 tag_errors = []
dgn38736db2015-09-18 19:20:512119 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:122120 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:222121
2122 for f in input_api.AffectedSourceFiles(sources):
2123 file_content = input_api.ReadFile(f)
2124 has_modified_logs = False
2125
2126 # Per line checks
dgn87d9fb62015-06-12 09:15:122127 if (cr_log_import_pattern.search(file_content) or
2128 (class_in_base_pattern.search(file_content) and
2129 not has_some_log_import_pattern.search(file_content))):
2130 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:222131 for line_num, line in f.ChangedContents():
2132
2133 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:122134 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:222135 if match:
2136 has_modified_logs = True
2137
2138 # Make sure it uses "TAG"
2139 if not match.group('tag') == 'TAG':
2140 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:122141 else:
2142 # Report non cr Log function calls in changed lines
2143 for line_num, line in f.ChangedContents():
2144 if log_call_pattern.search(line):
2145 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:222146
2147 # Per file checks
2148 if has_modified_logs:
2149 # Make sure the tag is using the "cr" prefix and is not too long
2150 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:512151 tag_name = match.group('name') if match else None
2152 if not tag_name:
dgnaa68d5e2015-06-10 10:08:222153 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512154 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:222155 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:512156 elif '.' in tag_name:
2157 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:222158
2159 results = []
2160 if tag_decl_errors:
2161 results.append(output_api.PresubmitPromptWarning(
2162 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:512163 '"private static final String TAG = "<package tag>".\n'
2164 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222165 tag_decl_errors))
2166
2167 if tag_length_errors:
2168 results.append(output_api.PresubmitError(
2169 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:512170 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:222171 tag_length_errors))
2172
2173 if tag_errors:
2174 results.append(output_api.PresubmitPromptWarning(
2175 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
2176 tag_errors))
2177
dgn87d9fb62015-06-12 09:15:122178 if util_log_errors:
dgn4401aa52015-04-29 16:26:172179 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:122180 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
2181 util_log_errors))
2182
dgn38736db2015-09-18 19:20:512183 if tag_with_dot_errors:
2184 results.append(output_api.PresubmitPromptWarning(
2185 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
2186 tag_with_dot_errors))
2187
dgn4401aa52015-04-29 16:26:172188 return results
2189
2190
Yoland Yanb92fa522017-08-28 17:37:062191def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
2192 """Checks that junit.framework.* is no longer used."""
2193 deprecated_junit_framework_pattern = input_api.re.compile(
2194 r'^import junit\.framework\..*;',
2195 input_api.re.MULTILINE)
2196 sources = lambda x: input_api.FilterSourceFile(
2197 x, white_list=(r'.*\.java$',), black_list=None)
2198 errors = []
2199 for f in input_api.AffectedFiles(sources):
2200 for line_num, line in f.ChangedContents():
2201 if deprecated_junit_framework_pattern.search(line):
2202 errors.append("%s:%d" % (f.LocalPath(), line_num))
2203
2204 results = []
2205 if errors:
2206 results.append(output_api.PresubmitError(
2207 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
2208 '(org.junit.*) from //third_party/junit. Contact [email protected]'
2209 ' if you have any question.', errors))
2210 return results
2211
2212
2213def _CheckAndroidTestJUnitInheritance(input_api, output_api):
2214 """Checks that if new Java test classes have inheritance.
2215 Either the new test class is JUnit3 test or it is a JUnit4 test class
2216 with a base class, either case is undesirable.
2217 """
2218 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
2219
2220 sources = lambda x: input_api.FilterSourceFile(
2221 x, white_list=(r'.*Test\.java$',), black_list=None)
2222 errors = []
2223 for f in input_api.AffectedFiles(sources):
2224 if not f.OldContents():
2225 class_declaration_start_flag = False
2226 for line_num, line in f.ChangedContents():
2227 if class_declaration_pattern.search(line):
2228 class_declaration_start_flag = True
2229 if class_declaration_start_flag and ' extends ' in line:
2230 errors.append('%s:%d' % (f.LocalPath(), line_num))
2231 if '{' in line:
2232 class_declaration_start_flag = False
2233
2234 results = []
2235 if errors:
2236 results.append(output_api.PresubmitPromptWarning(
2237 'The newly created files include Test classes that inherits from base'
2238 ' class. Please do not use inheritance in JUnit4 tests or add new'
2239 ' JUnit3 tests. Contact [email protected] if you have any'
2240 ' questions.', errors))
2241 return results
2242
yolandyan45001472016-12-21 21:12:422243def _CheckAndroidTestAnnotationUsage(input_api, output_api):
2244 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
2245 deprecated_annotation_import_pattern = input_api.re.compile(
2246 r'^import android\.test\.suitebuilder\.annotation\..*;',
2247 input_api.re.MULTILINE)
2248 sources = lambda x: input_api.FilterSourceFile(
2249 x, white_list=(r'.*\.java$',), black_list=None)
2250 errors = []
2251 for f in input_api.AffectedFiles(sources):
2252 for line_num, line in f.ChangedContents():
2253 if deprecated_annotation_import_pattern.search(line):
2254 errors.append("%s:%d" % (f.LocalPath(), line_num))
2255
2256 results = []
2257 if errors:
2258 results.append(output_api.PresubmitError(
2259 'Annotations in android.test.suitebuilder.annotation have been'
2260 ' deprecated since API level 24. Please use android.support.test.filters'
2261 ' from //third_party/android_support_test_runner:runner_java instead.'
2262 ' Contact [email protected] if you have any questions.', errors))
2263 return results
2264
2265
agrieve7b6479d82015-10-07 14:24:222266def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
2267 """Checks if MDPI assets are placed in a correct directory."""
2268 file_filter = lambda f: (f.LocalPath().endswith('.png') and
2269 ('/res/drawable/' in f.LocalPath() or
2270 '/res/drawable-ldrtl/' in f.LocalPath()))
2271 errors = []
2272 for f in input_api.AffectedFiles(include_deletes=False,
2273 file_filter=file_filter):
2274 errors.append(' %s' % f.LocalPath())
2275
2276 results = []
2277 if errors:
2278 results.append(output_api.PresubmitError(
2279 'MDPI assets should be placed in /res/drawable-mdpi/ or '
2280 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
2281 '/res/drawable-ldrtl/.\n'
2282 'Contact [email protected] if you have questions.', errors))
2283 return results
2284
2285
Nate Fischer535972b2017-09-16 01:06:182286def _CheckAndroidWebkitImports(input_api, output_api):
2287 """Checks that code uses org.chromium.base.Callback instead of
2288 android.widget.ValueCallback except in the WebView glue layer.
2289 """
2290 valuecallback_import_pattern = input_api.re.compile(
2291 r'^import android\.webkit\.ValueCallback;$')
2292
2293 errors = []
2294
2295 sources = lambda affected_file: input_api.FilterSourceFile(
2296 affected_file,
2297 black_list=(_EXCLUDED_PATHS +
2298 _TEST_CODE_EXCLUDED_PATHS +
2299 input_api.DEFAULT_BLACK_LIST +
2300 (r'^android_webview[\\\/]glue[\\\/].*',)),
2301 white_list=(r'.*\.java$',))
2302
2303 for f in input_api.AffectedSourceFiles(sources):
2304 for line_num, line in f.ChangedContents():
2305 if valuecallback_import_pattern.search(line):
2306 errors.append("%s:%d" % (f.LocalPath(), line_num))
2307
2308 results = []
2309
2310 if errors:
2311 results.append(output_api.PresubmitError(
2312 'android.webkit.ValueCallback usage is detected outside of the glue'
2313 ' layer. To stay compatible with the support library, android.webkit.*'
2314 ' classes should only be used inside the glue layer and'
2315 ' org.chromium.base.Callback should be used instead.',
2316 errors))
2317
2318 return results
2319
2320
agrievef32bcc72016-04-04 14:57:402321class PydepsChecker(object):
2322 def __init__(self, input_api, pydeps_files):
2323 self._file_cache = {}
2324 self._input_api = input_api
2325 self._pydeps_files = pydeps_files
2326
2327 def _LoadFile(self, path):
2328 """Returns the list of paths within a .pydeps file relative to //."""
2329 if path not in self._file_cache:
2330 with open(path) as f:
2331 self._file_cache[path] = f.read()
2332 return self._file_cache[path]
2333
2334 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
2335 """Returns an interable of paths within the .pydep, relativized to //."""
2336 os_path = self._input_api.os_path
2337 pydeps_dir = os_path.dirname(pydeps_path)
2338 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2339 if not l.startswith('*'))
2340 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2341
2342 def _CreateFilesToPydepsMap(self):
2343 """Returns a map of local_path -> list_of_pydeps."""
2344 ret = {}
2345 for pydep_local_path in self._pydeps_files:
2346 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2347 ret.setdefault(path, []).append(pydep_local_path)
2348 return ret
2349
2350 def ComputeAffectedPydeps(self):
2351 """Returns an iterable of .pydeps files that might need regenerating."""
2352 affected_pydeps = set()
2353 file_to_pydeps_map = None
2354 for f in self._input_api.AffectedFiles(include_deletes=True):
2355 local_path = f.LocalPath()
2356 if local_path == 'DEPS':
2357 return self._pydeps_files
2358 elif local_path.endswith('.pydeps'):
2359 if local_path in self._pydeps_files:
2360 affected_pydeps.add(local_path)
2361 elif local_path.endswith('.py'):
2362 if file_to_pydeps_map is None:
2363 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2364 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2365 return affected_pydeps
2366
2367 def DetermineIfStale(self, pydeps_path):
2368 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412369 import difflib
John Budorick47ca3fe2018-02-10 00:53:102370 import os
2371
agrievef32bcc72016-04-04 14:57:402372 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2373 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:102374 env = dict(os.environ)
2375 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:402376 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:102377 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412378 old_contents = old_pydeps_data[2:]
2379 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402380 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412381 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402382
2383
2384def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2385 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:402386 # This check is for Python dependency lists (.pydeps files), and involves
2387 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
2388 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:282389 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002390 return []
Mostyn Bramley-Moore6b427322017-12-21 22:11:022391 # TODO(agrieve): Update when there's a better way to detect
2392 # this: crbug.com/570091
agrievef32bcc72016-04-04 14:57:402393 is_android = input_api.os_path.exists('third_party/android_tools')
2394 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2395 results = []
2396 # First, check for new / deleted .pydeps.
2397 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:032398 # Check whether we are running the presubmit check for a file in src.
2399 # f.LocalPath is relative to repo (src, or internal repo).
2400 # os_path.exists is relative to src repo.
2401 # Therefore if os_path.exists is true, it means f.LocalPath is relative
2402 # to src and we can conclude that the pydeps is in src.
2403 if input_api.os_path.exists(f.LocalPath()):
2404 if f.LocalPath().endswith('.pydeps'):
2405 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2406 results.append(output_api.PresubmitError(
2407 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2408 'remove %s' % f.LocalPath()))
2409 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2410 results.append(output_api.PresubmitError(
2411 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2412 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:402413
2414 if results:
2415 return results
2416
2417 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2418
2419 for pydep_path in checker.ComputeAffectedPydeps():
2420 try:
phajdan.jr0d9878552016-11-04 10:49:412421 result = checker.DetermineIfStale(pydep_path)
2422 if result:
2423 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402424 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412425 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2426 'To regenerate, run:\n\n %s' %
2427 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402428 except input_api.subprocess.CalledProcessError as error:
2429 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2430 long_text=error.output)]
2431
2432 return results
2433
2434
glidere61efad2015-02-18 17:39:432435def _CheckSingletonInHeaders(input_api, output_api):
2436 """Checks to make sure no header files have |Singleton<|."""
2437 def FileFilter(affected_file):
2438 # It's ok for base/memory/singleton.h to have |Singleton<|.
2439 black_list = (_EXCLUDED_PATHS +
2440 input_api.DEFAULT_BLACK_LIST +
Michael Warrese4451492018-03-07 04:42:472441 (r"^base[\\\/]memory[\\\/]singleton\.h$",
2442 r"^net[\\\/]quic[\\\/]platform[\\\/]impl[\\\/]"
2443 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:432444 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2445
sergeyu34d21222015-09-16 00:11:442446 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432447 files = []
2448 for f in input_api.AffectedSourceFiles(FileFilter):
2449 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2450 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2451 contents = input_api.ReadFile(f)
2452 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242453 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432454 pattern.search(line)):
2455 files.append(f)
2456 break
2457
2458 if files:
yolandyandaabc6d2016-04-18 18:29:392459 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442460 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432461 'Please move them to an appropriate source file so that the ' +
2462 'template gets instantiated in a single compilation unit.',
2463 files) ]
2464 return []
2465
2466
[email protected]fd20b902014-05-09 02:14:532467_DEPRECATED_CSS = [
2468 # Values
2469 ( "-webkit-box", "flex" ),
2470 ( "-webkit-inline-box", "inline-flex" ),
2471 ( "-webkit-flex", "flex" ),
2472 ( "-webkit-inline-flex", "inline-flex" ),
2473 ( "-webkit-min-content", "min-content" ),
2474 ( "-webkit-max-content", "max-content" ),
2475
2476 # Properties
2477 ( "-webkit-background-clip", "background-clip" ),
2478 ( "-webkit-background-origin", "background-origin" ),
2479 ( "-webkit-background-size", "background-size" ),
2480 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442481 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532482
2483 # Functions
2484 ( "-webkit-gradient", "gradient" ),
2485 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2486 ( "-webkit-linear-gradient", "linear-gradient" ),
2487 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2488 ( "-webkit-radial-gradient", "radial-gradient" ),
2489 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2490]
2491
dbeam1ec68ac2016-12-15 05:22:242492def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532493 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252494 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342495 documentation and iOS CSS for dom distiller
2496 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252497 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532498 results = []
dbeam070cfe62014-10-22 06:44:022499 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252500 black_list = (_EXCLUDED_PATHS +
2501 _TEST_CODE_EXCLUDED_PATHS +
2502 input_api.DEFAULT_BLACK_LIST +
2503 (r"^chrome/common/extensions/docs",
2504 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342505 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442506 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252507 r"^native_client_sdk"))
2508 file_filter = lambda f: input_api.FilterSourceFile(
2509 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532510 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2511 for line_num, line in fpath.ChangedContents():
2512 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022513 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532514 results.append(output_api.PresubmitError(
2515 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2516 (fpath.LocalPath(), line_num, deprecated_value, value)))
2517 return results
2518
mohan.reddyf21db962014-10-16 12:26:472519
dbeam070cfe62014-10-22 06:44:022520_DEPRECATED_JS = [
2521 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2522 ( "__defineGetter__", "Object.defineProperty" ),
2523 ( "__defineSetter__", "Object.defineProperty" ),
2524]
2525
dbeam1ec68ac2016-12-15 05:22:242526def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022527 """Make sure that we don't use deprecated JS in Chrome code."""
2528 results = []
2529 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2530 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2531 input_api.DEFAULT_BLACK_LIST)
2532 file_filter = lambda f: input_api.FilterSourceFile(
2533 f, white_list=file_inclusion_pattern, black_list=black_list)
2534 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2535 for lnum, line in fpath.ChangedContents():
2536 for (deprecated, replacement) in _DEPRECATED_JS:
2537 if deprecated in line:
2538 results.append(output_api.PresubmitError(
2539 "%s:%d: Use of deprecated JS %s, use %s instead" %
2540 (fpath.LocalPath(), lnum, deprecated, replacement)))
2541 return results
2542
dpapadd651231d82017-07-21 02:44:472543def _CheckForRiskyJsArrowFunction(line_number, line):
2544 if ' => ' in line:
2545 return "line %d, is using an => (arrow) function\n %s\n" % (
2546 line_number, line)
2547 return ''
2548
2549def _CheckForRiskyJsConstLet(input_api, line_number, line):
2550 if input_api.re.match('^\s*(const|let)\s', line):
2551 return "line %d, is using const/let keyword\n %s\n" % (
2552 line_number, line)
2553 return ''
dbeam070cfe62014-10-22 06:44:022554
dbeam1ec68ac2016-12-15 05:22:242555def _CheckForRiskyJsFeatures(input_api, output_api):
2556 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002557 # 'ui/webui/resources/cr_components are not allowed on ios'
2558 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572559 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002560 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472561 results = []
dbeam1ec68ac2016-12-15 05:22:242562 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472563 arrow_error_lines = []
2564 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242565 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472566 arrow_error_lines += filter(None, [
2567 _CheckForRiskyJsArrowFunction(lnum, line),
2568 ])
dbeam1ec68ac2016-12-15 05:22:242569
dpapadd651231d82017-07-21 02:44:472570 const_let_error_lines += filter(None, [
2571 _CheckForRiskyJsConstLet(input_api, lnum, line),
2572 ])
dbeam1ec68ac2016-12-15 05:22:242573
dpapadd651231d82017-07-21 02:44:472574 if arrow_error_lines:
2575 arrow_error_lines = map(
2576 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2577 results.append(
2578 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2579"""
2580Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242581%s
2582Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2583https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472584""" % f.LocalPath()
2585 ])))
dbeam1ec68ac2016-12-15 05:22:242586
dpapadd651231d82017-07-21 02:44:472587 if const_let_error_lines:
2588 const_let_error_lines = map(
2589 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2590 results.append(
2591 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2592"""
2593Use of const/let keywords detected in:
2594%s
2595Please ensure your code does not run on iOS9 because const/let is not fully
2596supported.
2597https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2598https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2599""" % f.LocalPath()
2600 ])))
2601
2602 return results
dbeam1ec68ac2016-12-15 05:22:242603
rlanday6802cf632017-05-30 17:48:362604def _CheckForRelativeIncludes(input_api, output_api):
2605 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2606 import sys
2607 original_sys_path = sys.path
2608 try:
2609 sys.path = sys.path + [input_api.os_path.join(
2610 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2611 from cpp_checker import CppChecker
2612 finally:
2613 # Restore sys.path to what it was before.
2614 sys.path = original_sys_path
2615
2616 bad_files = {}
2617 for f in input_api.AffectedFiles(include_deletes=False):
2618 if (f.LocalPath().startswith('third_party') and
2619 not f.LocalPath().startswith('third_party/WebKit') and
2620 not f.LocalPath().startswith('third_party\\WebKit')):
2621 continue
2622
2623 if not CppChecker.IsCppFile(f.LocalPath()):
2624 continue
2625
Vaclav Brozekd5de76a2018-03-17 07:57:502626 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:362627 if "#include" in line and "../" in line]
2628 if not relative_includes:
2629 continue
2630 bad_files[f.LocalPath()] = relative_includes
2631
2632 if not bad_files:
2633 return []
2634
2635 error_descriptions = []
2636 for file_path, bad_lines in bad_files.iteritems():
2637 error_description = file_path
2638 for line in bad_lines:
2639 error_description += '\n ' + line
2640 error_descriptions.append(error_description)
2641
2642 results = []
2643 results.append(output_api.PresubmitError(
2644 'You added one or more relative #include paths (including "../").\n'
2645 'These shouldn\'t be used because they can be used to include headers\n'
2646 'from code that\'s not correctly specified as a dependency in the\n'
2647 'relevant BUILD.gn file(s).',
2648 error_descriptions))
2649
2650 return results
2651
Takeshi Yoshinoe387aa32017-08-02 13:16:132652
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202653def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2654 if not isinstance(key, ast.Str):
2655 return 'Key at line %d must be a string literal' % key.lineno
2656 if not isinstance(value, ast.Dict):
2657 return 'Value at line %d must be a dict' % value.lineno
2658 if len(value.keys) != 1:
2659 return 'Dict at line %d must have single entry' % value.lineno
2660 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2661 return (
2662 'Entry at line %d must have a string literal \'filepath\' as key' %
2663 value.lineno)
2664 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132665
Takeshi Yoshinoe387aa32017-08-02 13:16:132666
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202667def _CheckWatchlistsEntrySyntax(key, value, ast):
2668 if not isinstance(key, ast.Str):
2669 return 'Key at line %d must be a string literal' % key.lineno
2670 if not isinstance(value, ast.List):
2671 return 'Value at line %d must be a list' % value.lineno
2672 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132673
Takeshi Yoshinoe387aa32017-08-02 13:16:132674
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202675def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2676 mismatch_template = (
2677 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2678 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132679
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202680 i = 0
2681 last_key = ''
2682 while True:
2683 if i >= len(wd_dict.keys):
2684 if i >= len(w_dict.keys):
2685 return None
2686 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2687 elif i >= len(w_dict.keys):
2688 return (
2689 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132690
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202691 wd_key = wd_dict.keys[i]
2692 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132693
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202694 result = _CheckWatchlistDefinitionsEntrySyntax(
2695 wd_key, wd_dict.values[i], ast)
2696 if result is not None:
2697 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132698
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202699 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2700 if result is not None:
2701 return 'Bad entry in WATCHLISTS dict: %s' % result
2702
2703 if wd_key.s != w_key.s:
2704 return mismatch_template % (
2705 '%s at line %d' % (wd_key.s, wd_key.lineno),
2706 '%s at line %d' % (w_key.s, w_key.lineno))
2707
2708 if wd_key.s < last_key:
2709 return (
2710 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2711 (wd_key.lineno, w_key.lineno))
2712 last_key = wd_key.s
2713
2714 i = i + 1
2715
2716
2717def _CheckWATCHLISTSSyntax(expression, ast):
2718 if not isinstance(expression, ast.Expression):
2719 return 'WATCHLISTS file must contain a valid expression'
2720 dictionary = expression.body
2721 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2722 return 'WATCHLISTS file must have single dict with exactly two entries'
2723
2724 first_key = dictionary.keys[0]
2725 first_value = dictionary.values[0]
2726 second_key = dictionary.keys[1]
2727 second_value = dictionary.values[1]
2728
2729 if (not isinstance(first_key, ast.Str) or
2730 first_key.s != 'WATCHLIST_DEFINITIONS' or
2731 not isinstance(first_value, ast.Dict)):
2732 return (
2733 'The first entry of the dict in WATCHLISTS file must be '
2734 'WATCHLIST_DEFINITIONS dict')
2735
2736 if (not isinstance(second_key, ast.Str) or
2737 second_key.s != 'WATCHLISTS' or
2738 not isinstance(second_value, ast.Dict)):
2739 return (
2740 'The second entry of the dict in WATCHLISTS file must be '
2741 'WATCHLISTS dict')
2742
2743 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132744
2745
2746def _CheckWATCHLISTS(input_api, output_api):
2747 for f in input_api.AffectedFiles(include_deletes=False):
2748 if f.LocalPath() == 'WATCHLISTS':
2749 contents = input_api.ReadFile(f, 'r')
2750
2751 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202752 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132753 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202754 # Get an AST tree for it and scan the tree for detailed style checking.
2755 expression = input_api.ast.parse(
2756 contents, filename='WATCHLISTS', mode='eval')
2757 except ValueError as e:
2758 return [output_api.PresubmitError(
2759 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2760 except SyntaxError as e:
2761 return [output_api.PresubmitError(
2762 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2763 except TypeError as e:
2764 return [output_api.PresubmitError(
2765 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132766
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202767 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2768 if result is not None:
2769 return [output_api.PresubmitError(result)]
2770 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132771
2772 return []
2773
2774
dgnaa68d5e2015-06-10 10:08:222775def _AndroidSpecificOnUploadChecks(input_api, output_api):
2776 """Groups checks that target android code."""
2777 results = []
dgnaa68d5e2015-06-10 10:08:222778 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222779 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292780 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062781 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2782 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422783 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182784 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222785 return results
2786
2787
[email protected]22c9bd72011-03-27 16:47:392788def _CommonChecks(input_api, output_api):
2789 """Checks common to both upload and commit."""
2790 results = []
2791 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382792 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542793 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:082794
2795 author = input_api.change.author_email
2796 if author and author not in _KNOWN_ROBOTS:
2797 results.extend(
2798 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
2799
[email protected]55459852011-08-10 15:17:192800 results.extend(
[email protected]760deea2013-12-10 19:33:492801 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:232802 results.extend(
2803 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542804 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182805 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522806 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222807 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442808 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592809 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062810 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122811 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182812 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222813 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302814 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492815 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032816 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492817 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442818 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272819 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072820 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542821 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442822 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392823 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552824 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042825 results.extend(
2826 input_api.canned_checks.CheckChangeHasNoTabs(
2827 input_api,
2828 output_api,
2829 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402830 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162831 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082832 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242833 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2834 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472835 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042836 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:052837 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:142838 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232839 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432840 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402841 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152842 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172843 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502844 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242845 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362846 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132847 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432848 results.extend(input_api.RunTests(
2849 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242850
Vaclav Brozekcdc7defb2018-03-20 09:54:352851 for f in input_api.AffectedFiles():
2852 path, name = input_api.os_path.split(f.LocalPath())
2853 if name == 'PRESUBMIT.py':
2854 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:002855 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
2856 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:072857 # The PRESUBMIT.py file (and the directory containing it) might
2858 # have been affected by being moved or removed, so only try to
2859 # run the tests if they still exist.
2860 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2861 input_api, output_api, full_path,
2862 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392863 return results
[email protected]1f7b4172010-01-28 01:17:342864
[email protected]b337cb5b2011-01-23 21:24:052865
[email protected]b8079ae4a2012-12-05 19:56:492866def _CheckPatchFiles(input_api, output_api):
2867 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2868 if f.LocalPath().endswith(('.orig', '.rej'))]
2869 if problems:
2870 return [output_api.PresubmitError(
2871 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032872 else:
2873 return []
[email protected]b8079ae4a2012-12-05 19:56:492874
2875
Kent Tamura5a8755d2017-06-29 23:37:072876def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212877 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2878 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2879 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072880 include_re = input_api.re.compile(
2881 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2882 extension_re = input_api.re.compile(r'\.[a-z]+$')
2883 errors = []
2884 for f in input_api.AffectedFiles():
2885 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2886 continue
2887 found_line_number = None
2888 found_macro = None
2889 for line_num, line in f.ChangedContents():
2890 match = macro_re.search(line)
2891 if match:
2892 found_line_number = line_num
2893 found_macro = match.group(2)
2894 break
2895 if not found_line_number:
2896 continue
2897
2898 found_include = False
2899 for line in f.NewContents():
2900 if include_re.search(line):
2901 found_include = True
2902 break
2903 if found_include:
2904 continue
2905
2906 if not f.LocalPath().endswith('.h'):
2907 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2908 try:
2909 content = input_api.ReadFile(primary_header_path, 'r')
2910 if include_re.search(content):
2911 continue
2912 except IOError:
2913 pass
2914 errors.append('%s:%d %s macro is used without including build/'
2915 'build_config.h.'
2916 % (f.LocalPath(), found_line_number, found_macro))
2917 if errors:
2918 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2919 return []
2920
2921
[email protected]b00342e7f2013-03-26 16:21:542922def _DidYouMeanOSMacro(bad_macro):
2923 try:
2924 return {'A': 'OS_ANDROID',
2925 'B': 'OS_BSD',
2926 'C': 'OS_CHROMEOS',
2927 'F': 'OS_FREEBSD',
2928 'L': 'OS_LINUX',
2929 'M': 'OS_MACOSX',
2930 'N': 'OS_NACL',
2931 'O': 'OS_OPENBSD',
2932 'P': 'OS_POSIX',
2933 'S': 'OS_SOLARIS',
2934 'W': 'OS_WIN'}[bad_macro[3].upper()]
2935 except KeyError:
2936 return ''
2937
2938
2939def _CheckForInvalidOSMacrosInFile(input_api, f):
2940 """Check for sensible looking, totally invalid OS macros."""
2941 preprocessor_statement = input_api.re.compile(r'^\s*#')
2942 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2943 results = []
2944 for lnum, line in f.ChangedContents():
2945 if preprocessor_statement.search(line):
2946 for match in os_macro.finditer(line):
2947 if not match.group(1) in _VALID_OS_MACROS:
2948 good = _DidYouMeanOSMacro(match.group(1))
2949 did_you_mean = ' (did you mean %s?)' % good if good else ''
2950 results.append(' %s:%d %s%s' % (f.LocalPath(),
2951 lnum,
2952 match.group(1),
2953 did_you_mean))
2954 return results
2955
2956
2957def _CheckForInvalidOSMacros(input_api, output_api):
2958 """Check all affected files for invalid OS macros."""
2959 bad_macros = []
2960 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472961 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542962 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2963
2964 if not bad_macros:
2965 return []
2966
2967 return [output_api.PresubmitError(
2968 'Possibly invalid OS macro[s] found. Please fix your code\n'
2969 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2970
lliabraa35bab3932014-10-01 12:16:442971
2972def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2973 """Check all affected files for invalid "if defined" macros."""
2974 ALWAYS_DEFINED_MACROS = (
2975 "TARGET_CPU_PPC",
2976 "TARGET_CPU_PPC64",
2977 "TARGET_CPU_68K",
2978 "TARGET_CPU_X86",
2979 "TARGET_CPU_ARM",
2980 "TARGET_CPU_MIPS",
2981 "TARGET_CPU_SPARC",
2982 "TARGET_CPU_ALPHA",
2983 "TARGET_IPHONE_SIMULATOR",
2984 "TARGET_OS_EMBEDDED",
2985 "TARGET_OS_IPHONE",
2986 "TARGET_OS_MAC",
2987 "TARGET_OS_UNIX",
2988 "TARGET_OS_WIN32",
2989 )
2990 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2991 results = []
2992 for lnum, line in f.ChangedContents():
2993 for match in ifdef_macro.finditer(line):
2994 if match.group(1) in ALWAYS_DEFINED_MACROS:
2995 always_defined = ' %s is always defined. ' % match.group(1)
2996 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2997 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2998 lnum,
2999 always_defined,
3000 did_you_mean))
3001 return results
3002
3003
3004def _CheckForInvalidIfDefinedMacros(input_api, output_api):
3005 """Check all affected files for invalid "if defined" macros."""
3006 bad_macros = []
3007 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:213008 if f.LocalPath().startswith('third_party/sqlite/'):
3009 continue
lliabraa35bab3932014-10-01 12:16:443010 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
3011 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
3012
3013 if not bad_macros:
3014 return []
3015
3016 return [output_api.PresubmitError(
3017 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
3018 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
3019 bad_macros)]
3020
3021
mlamouria82272622014-09-16 18:45:043022def _CheckForIPCRules(input_api, output_api):
3023 """Check for same IPC rules described in
3024 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
3025 """
3026 base_pattern = r'IPC_ENUM_TRAITS\('
3027 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
3028 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
3029
3030 problems = []
3031 for f in input_api.AffectedSourceFiles(None):
3032 local_path = f.LocalPath()
3033 if not local_path.endswith('.h'):
3034 continue
3035 for line_number, line in f.ChangedContents():
3036 if inclusion_pattern.search(line) and not comment_pattern.search(line):
3037 problems.append(
3038 '%s:%d\n %s' % (local_path, line_number, line.strip()))
3039
3040 if problems:
3041 return [output_api.PresubmitPromptWarning(
3042 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
3043 else:
3044 return []
3045
[email protected]b00342e7f2013-03-26 16:21:543046
Stephen Martinis97a394142018-06-07 23:06:053047def _CheckForLongPathnames(input_api, output_api):
3048 """Check to make sure no files being submitted have long paths.
3049 This causes issues on Windows.
3050 """
3051 problems = []
3052 for f in input_api.AffectedSourceFiles(None):
3053 local_path = f.LocalPath()
3054 # Windows has a path limit of 260 characters. Limit path length to 200 so
3055 # that we have some extra for the prefix on dev machines and the bots.
3056 if len(local_path) > 200:
3057 problems.append(local_path)
3058
3059 if problems:
3060 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
3061 else:
3062 return []
3063
3064
Daniel Bratell8ba52722018-03-02 16:06:143065def _CheckForIncludeGuards(input_api, output_api):
3066 """Check that header files have proper guards against multiple inclusion.
3067 If a file should not have such guards (and it probably should) then it
3068 should include the string "no-include-guard-because-multiply-included".
3069 """
Daniel Bratell6a75baef62018-06-04 10:04:453070 def is_chromium_header_file(f):
3071 # We only check header files under the control of the Chromium
3072 # project. That is, those outside third_party apart from
3073 # third_party/blink.
3074 file_with_path = input_api.os_path.normpath(f.LocalPath())
3075 return (file_with_path.endswith('.h') and
3076 (not file_with_path.startswith('third_party') or
3077 file_with_path.startswith(
3078 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:143079
3080 def replace_special_with_underscore(string):
3081 return input_api.re.sub(r'[\\/.-]', '_', string)
3082
3083 errors = []
3084
Daniel Bratell6a75baef62018-06-04 10:04:453085 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:143086 guard_name = None
3087 guard_line_number = None
3088 seen_guard_end = False
3089
3090 file_with_path = input_api.os_path.normpath(f.LocalPath())
3091 base_file_name = input_api.os_path.splitext(
3092 input_api.os_path.basename(file_with_path))[0]
3093 upper_base_file_name = base_file_name.upper()
3094
3095 expected_guard = replace_special_with_underscore(
3096 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:143097
3098 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:573099 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
3100 # are too many (1000+) files with slight deviations from the
3101 # coding style. The most important part is that the include guard
3102 # is there, and that it's unique, not the name so this check is
3103 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:143104 #
3105 # As code becomes more uniform, this could be made stricter.
3106
3107 guard_name_pattern_list = [
3108 # Anything with the right suffix (maybe with an extra _).
3109 r'\w+_H__?',
3110
Daniel Bratell39b5b062018-05-16 18:09:573111 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:143112 r'\w+_h',
3113
3114 # Anything including the uppercase name of the file.
3115 r'\w*' + input_api.re.escape(replace_special_with_underscore(
3116 upper_base_file_name)) + r'\w*',
3117 ]
3118 guard_name_pattern = '|'.join(guard_name_pattern_list)
3119 guard_pattern = input_api.re.compile(
3120 r'#ifndef\s+(' + guard_name_pattern + ')')
3121
3122 for line_number, line in enumerate(f.NewContents()):
3123 if 'no-include-guard-because-multiply-included' in line:
3124 guard_name = 'DUMMY' # To not trigger check outside the loop.
3125 break
3126
3127 if guard_name is None:
3128 match = guard_pattern.match(line)
3129 if match:
3130 guard_name = match.group(1)
3131 guard_line_number = line_number
3132
Daniel Bratell39b5b062018-05-16 18:09:573133 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:453134 # don't match the chromium style guide, but new files should
3135 # get it right.
3136 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:573137 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:143138 errors.append(output_api.PresubmitPromptWarning(
3139 'Header using the wrong include guard name %s' % guard_name,
3140 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Daniel Bratell39b5b062018-05-16 18:09:573141 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:143142 else:
3143 # The line after #ifndef should have a #define of the same name.
3144 if line_number == guard_line_number + 1:
3145 expected_line = '#define %s' % guard_name
3146 if line != expected_line:
3147 errors.append(output_api.PresubmitPromptWarning(
3148 'Missing "%s" for include guard' % expected_line,
3149 ['%s:%d' % (f.LocalPath(), line_number + 1)],
3150 'Expected: %r\nGot: %r' % (expected_line, line)))
3151
3152 if not seen_guard_end and line == '#endif // %s' % guard_name:
3153 seen_guard_end = True
3154 elif seen_guard_end:
3155 if line.strip() != '':
3156 errors.append(output_api.PresubmitPromptWarning(
3157 'Include guard %s not covering the whole file' % (
3158 guard_name), [f.LocalPath()]))
3159 break # Nothing else to check and enough to warn once.
3160
3161 if guard_name is None:
3162 errors.append(output_api.PresubmitPromptWarning(
3163 'Missing include guard %s' % expected_guard,
3164 [f.LocalPath()],
3165 'Missing include guard in %s\n'
3166 'Recommended name: %s\n'
3167 'This check can be disabled by having the string\n'
3168 'no-include-guard-because-multiply-included in the header.' %
3169 (f.LocalPath(), expected_guard)))
3170
3171 return errors
3172
3173
mostynbb639aca52015-01-07 20:31:233174def _CheckForWindowsLineEndings(input_api, output_api):
3175 """Check source code and known ascii text files for Windows style line
3176 endings.
3177 """
earthdok1b5e0ee2015-03-10 15:19:103178 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:233179
3180 file_inclusion_pattern = (
3181 known_text_files,
3182 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3183 )
3184
mostynbb639aca52015-01-07 20:31:233185 problems = []
Andrew Grieve933d12e2017-10-30 20:22:533186 source_file_filter = lambda f: input_api.FilterSourceFile(
3187 f, white_list=file_inclusion_pattern, black_list=None)
3188 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:503189 include_file = False
3190 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:233191 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:503192 include_file = True
3193 if include_file:
3194 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:233195
3196 if problems:
3197 return [output_api.PresubmitPromptWarning('Are you sure that you want '
3198 'these files to contain Windows style line endings?\n' +
3199 '\n'.join(problems))]
3200
3201 return []
3202
3203
Vaclav Brozekd5de76a2018-03-17 07:57:503204def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:133205 """Checks that all source files use SYSLOG properly."""
3206 syslog_files = []
3207 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:563208 for line_number, line in f.ChangedContents():
3209 if 'SYSLOG' in line:
3210 syslog_files.append(f.LocalPath() + ':' + str(line_number))
3211
pastarmovj89f7ee12016-09-20 14:58:133212 if syslog_files:
3213 return [output_api.PresubmitPromptWarning(
3214 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
3215 ' calls.\nFiles to check:\n', items=syslog_files)]
3216 return []
3217
3218
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193219def _CheckCrbugLinksHaveHttps(input_api, output_api):
Miguel Casas68bdb652017-12-19 16:29:093220 """Checks that crbug(.com) links are correctly prefixed by https://,
3221 unless they come in the accepted form TODO(crbug.com/...)
3222 """
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193223 white_list = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
3224 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS)
3225 sources = lambda f: input_api.FilterSourceFile(
3226 f, white_list=white_list, black_list=black_list)
3227
3228 pattern = input_api.re.compile(r'//.*(?<!:\/\/)crbug[.com]*')
Miguel Casas68bdb652017-12-19 16:29:093229 accepted_pattern = input_api.re.compile(r'//.*TODO\(crbug[.com]*');
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193230 problems = []
3231 for f in input_api.AffectedSourceFiles(sources):
3232 for line_num, line in f.ChangedContents():
Miguel Casas68bdb652017-12-19 16:29:093233 if pattern.search(line) and not accepted_pattern.search(line):
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193234 problems.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
3235
3236 if problems:
3237 return [output_api.PresubmitPromptWarning(
3238 'Found unprefixed crbug.com URL(s), consider prepending https://\n'+
3239 '\n'.join(problems))]
3240 return []
3241
3242
[email protected]1f7b4172010-01-28 01:17:343243def CheckChangeOnUpload(input_api, output_api):
3244 results = []
3245 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:473246 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:283247 results.extend(
jam93a6ee792017-02-08 23:59:223248 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:193249 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:223250 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:133251 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:163252 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Miguel Casas-Sancheze0d46d42017-12-14 15:52:193253 results.extend(_CheckCrbugLinksHaveHttps(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:533254 results.extend(_CheckUniquePtr(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543255 return results
[email protected]ca8d1982009-02-19 16:33:123256
3257
[email protected]1bfb8322014-04-23 01:02:413258def GetTryServerMasterForBot(bot):
3259 """Returns the Try Server master for the given bot.
3260
[email protected]0bb112362014-07-26 04:38:323261 It tries to guess the master from the bot name, but may still fail
3262 and return None. There is no longer a default master.
3263 """
3264 # Potentially ambiguous bot names are listed explicitly.
3265 master_map = {
tandriie5587792016-07-14 00:34:503266 'chromium_presubmit': 'master.tryserver.chromium.linux',
3267 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:413268 }
[email protected]0bb112362014-07-26 04:38:323269 master = master_map.get(bot)
3270 if not master:
wnwen4fbaab82016-05-25 12:54:363271 if 'android' in bot:
tandriie5587792016-07-14 00:34:503272 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:363273 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:503274 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:323275 elif 'win' in bot:
tandriie5587792016-07-14 00:34:503276 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:323277 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:503278 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:323279 return master
[email protected]1bfb8322014-04-23 01:02:413280
3281
[email protected]ca8d1982009-02-19 16:33:123282def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:543283 results = []
[email protected]1f7b4172010-01-28 01:17:343284 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543285 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:273286 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:343287 input_api,
3288 output_api,
[email protected]2fdd1f362013-01-16 03:56:033289 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:273290
jam93a6ee792017-02-08 23:59:223291 results.extend(
3292 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:543293 results.extend(input_api.canned_checks.CheckChangeHasBugField(
3294 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:413295 results.extend(input_api.canned_checks.CheckChangeHasDescription(
3296 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:543297 return results