blob: 01118f903511c3e4d10a965c7a070c19e15c730f [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$",
ehmaldonado78eee2ed2017-03-28 13:16:5427 # Test pages for WebRTC telemetry tests.
28 r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4029)
[email protected]ca8d1982009-02-19 16:33:1230
wnwenbdc444e2016-05-25 13:44:1531
[email protected]06e6d0ff2012-12-11 01:36:4432# Fragment of a regular expression that matches C++ and Objective-C++
33# implementation files.
34_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
35
wnwenbdc444e2016-05-25 13:44:1536
[email protected]06e6d0ff2012-12-11 01:36:4437# Regular expression that matches code only used for test binaries
38# (best effort).
39_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4940 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4441 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
sdefresne1fccb0a2016-12-19 08:10:5342 r'.+_(api|browser|eg|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1243 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4444 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4945 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0546 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4947 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4748 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4949 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0850 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4951 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4452)
[email protected]ca8d1982009-02-19 16:33:1253
wnwenbdc444e2016-05-25 13:44:1554
[email protected]eea609a2011-11-18 13:10:1255_TEST_ONLY_WARNING = (
56 'You might be calling functions intended only for testing from\n'
57 'production code. It is OK to ignore this warning if you know what\n'
58 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5859 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1260
61
[email protected]cf9b78f2012-11-14 11:40:2862_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4063 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2164 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
65 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2866
wnwenbdc444e2016-05-25 13:44:1567
Eric Stevensona9a980972017-09-23 00:04:4168_BANNED_JAVA_FUNCTIONS = (
69 (
70 'StrictMode.allowThreadDiskReads()',
71 (
72 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
73 'directly.',
74 ),
75 False,
76 ),
77 (
78 'StrictMode.allowThreadDiskWrites()',
79 (
80 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
81 'directly.',
82 ),
83 False,
84 ),
85)
86
[email protected]127f18ec2012-06-16 05:05:5987_BANNED_OBJC_FUNCTIONS = (
88 (
89 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2090 (
91 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5992 'prohibited. Please use CrTrackingArea instead.',
93 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
94 ),
95 False,
96 ),
97 (
[email protected]eaae1972014-04-16 04:17:2698 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2099 (
100 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59101 'instead.',
102 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
103 ),
104 False,
105 ),
106 (
107 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20108 (
109 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59110 'Please use |convertPoint:(point) fromView:nil| instead.',
111 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
112 ),
113 True,
114 ),
115 (
116 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20117 (
118 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59119 'Please use |convertPoint:(point) toView:nil| instead.',
120 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
121 ),
122 True,
123 ),
124 (
125 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20126 (
127 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59128 'Please use |convertRect:(point) fromView:nil| instead.',
129 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
130 ),
131 True,
132 ),
133 (
134 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20135 (
136 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59137 'Please use |convertRect:(point) toView:nil| instead.',
138 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
139 ),
140 True,
141 ),
142 (
143 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20144 (
145 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59146 'Please use |convertSize:(point) fromView:nil| instead.',
147 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
148 ),
149 True,
150 ),
151 (
152 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20153 (
154 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59155 'Please use |convertSize:(point) toView:nil| instead.',
156 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
157 ),
158 True,
159 ),
jif65398702016-10-27 10:19:48160 (
161 r"/\s+UTF8String\s*]",
162 (
163 'The use of -[NSString UTF8String] is dangerous as it can return null',
164 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
165 'Please use |SysNSStringToUTF8| instead.',
166 ),
167 True,
168 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34169 (
170 r'__unsafe_unretained',
171 (
172 'The use of __unsafe_unretained is almost certainly wrong, unless',
173 'when interacting with NSFastEnumeration or NSInvocation.',
174 'Please use __weak in files build with ARC, nothing otherwise.',
175 ),
176 False,
177 ),
[email protected]127f18ec2012-06-16 05:05:59178)
179
180
181_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20182 # Make sure that gtest's FRIEND_TEST() macro is not used; the
183 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30184 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20185 (
thomasandersone7caaa9b2017-03-29 19:22:53186 r'\bNULL\b',
187 (
188 'New code should not use NULL. Use nullptr instead.',
189 ),
190 True,
191 (),
192 ),
193 (
[email protected]23e6cbc2012-06-16 18:51:20194 'FRIEND_TEST(',
195 (
[email protected]e3c945502012-06-26 20:01:49196 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20197 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
198 ),
199 False,
[email protected]7345da02012-11-27 14:31:49200 (),
[email protected]23e6cbc2012-06-16 18:51:20201 ),
202 (
thomasanderson4b569052016-09-14 20:15:53203 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
204 (
205 'Chrome clients wishing to select events on X windows should use',
206 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
207 'you are selecting events from the GPU process, or if you are using',
208 'an XDisplay other than gfx::GetXDisplay().',
209 ),
210 True,
211 (
212 r"^ui[\\\/]gl[\\\/].*\.cc$",
213 r"^media[\\\/]gpu[\\\/].*\.cc$",
214 r"^gpu[\\\/].*\.cc$",
215 ),
216 ),
217 (
thomasandersone043e3ce2017-06-08 00:43:20218 r'XInternAtom|xcb_intern_atom',
219 (
thomasanderson11aa41d2017-06-08 22:22:38220 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20221 ),
222 True,
223 (
thomasanderson11aa41d2017-06-08 22:22:38224 r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$",
225 r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20226 r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$",
227 ),
228 ),
229 (
tomhudsone2c14d552016-05-26 17:07:46230 'setMatrixClip',
231 (
232 'Overriding setMatrixClip() is prohibited; ',
233 'the base function is deprecated. ',
234 ),
235 True,
236 (),
237 ),
238 (
[email protected]52657f62013-05-20 05:30:31239 'SkRefPtr',
240 (
241 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22242 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31243 ),
244 True,
245 (),
246 ),
247 (
248 'SkAutoRef',
249 (
250 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22251 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31252 ),
253 True,
254 (),
255 ),
256 (
257 'SkAutoTUnref',
258 (
259 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22260 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31261 ),
262 True,
263 (),
264 ),
265 (
266 'SkAutoUnref',
267 (
268 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
269 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22270 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31271 ),
272 True,
273 (),
274 ),
[email protected]d89eec82013-12-03 14:10:59275 (
276 r'/HANDLE_EINTR\(.*close',
277 (
278 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
279 'descriptor will be closed, and it is incorrect to retry the close.',
280 'Either call close directly and ignore its return value, or wrap close',
281 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
282 ),
283 True,
284 (),
285 ),
286 (
287 r'/IGNORE_EINTR\((?!.*close)',
288 (
289 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
290 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
291 ),
292 True,
293 (
294 # Files that #define IGNORE_EINTR.
295 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
296 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
297 ),
298 ),
[email protected]ec5b3f02014-04-04 18:43:43299 (
300 r'/v8::Extension\(',
301 (
302 'Do not introduce new v8::Extensions into the code base, use',
303 'gin::Wrappable instead. See http://crbug.com/334679',
304 ),
305 True,
[email protected]f55c90ee62014-04-12 00:50:03306 (
joaodasilva718f87672014-08-30 09:25:49307 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03308 ),
[email protected]ec5b3f02014-04-04 18:43:43309 ),
skyostilf9469f72015-04-20 10:38:52310 (
jame2d1a952016-04-02 00:27:10311 '#pragma comment(lib,',
312 (
313 'Specify libraries to link with in build files and not in the source.',
314 ),
315 True,
316 (),
317 ),
fdorayc4ac18d2017-05-01 21:39:59318 (
Matt Falkenhagen82a076e02017-09-28 08:08:19319 r'/(WebThread|BrowserThread)::(FILE|FILE_USER_BLOCKING|DB|CACHE)',
Gabriel Charette664e4482017-06-13 19:55:29320 (
321 'The non-UI/IO BrowserThreads are deprecated, please migrate this',
322 'code to TaskScheduler. See https://goo.gl/mDSxKl for details.',
323 'For questions, contact base/task_scheduler/OWNERS.',
324 ),
325 True,
326 (),
327 ),
328 (
gabd52c912a2017-05-11 04:15:59329 'base::SequenceChecker',
330 (
331 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
332 ),
333 False,
334 (),
335 ),
336 (
337 'base::ThreadChecker',
338 (
339 'Consider using THREAD_CHECKER macros instead of the class directly.',
340 ),
341 False,
342 (),
343 ),
dbeamb6f4fde2017-06-15 04:03:06344 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06345 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
346 (
347 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
348 'deprecated (http://crbug.com/634507). Please avoid converting away',
349 'from the Time types in Chromium code, especially if any math is',
350 'being done on time values. For interfacing with platform/library',
351 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
352 'type converter methods instead. For faking TimeXXX values (for unit',
353 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
354 'other use cases, please contact base/time/OWNERS.',
355 ),
356 False,
357 (),
358 ),
359 (
dbeamb6f4fde2017-06-15 04:03:06360 'CallJavascriptFunctionUnsafe',
361 (
362 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
363 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
364 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
365 ),
366 False,
367 (
368 r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$',
369 r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$',
370 r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$',
371 ),
372 ),
dskiba1474c2bfd62017-07-20 02:19:24373 (
374 'leveldb::DB::Open',
375 (
376 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
377 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
378 "Chrome's tracing, making their memory usage visible.",
379 ),
380 True,
381 (
382 r'^third_party/leveldatabase/.*\.(cc|h)$',
383 ),
Gabriel Charette0592c3a2017-07-26 12:02:04384 ),
385 (
Chris Mumfordc38afb62017-10-09 17:55:08386 'leveldb::NewMemEnv',
387 (
388 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
389 'third_party/leveldatabase/leveldb_chrome.h.',
390 ),
391 True,
392 (
393 r'^third_party/leveldatabase/.*\.(cc|h)$',
394 ),
395 ),
396 (
Gabriel Charetted9839bc2017-07-29 14:17:47397 'MessageLoop::QuitWhenIdleClosure',
Gabriel Charette0592c3a2017-07-26 12:02:04398 (
Robert Liao64b7ab22017-08-04 23:03:43399 'MessageLoop::QuitWhenIdleClosure is deprecated. Please migrate to',
400 'Runloop.',
Gabriel Charette0592c3a2017-07-26 12:02:04401 ),
402 True,
403 (),
Gabriel Charetted9839bc2017-07-29 14:17:47404 ),
405 (
406 'RunLoop::QuitCurrent',
407 (
Robert Liao64b7ab22017-08-04 23:03:43408 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
409 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47410 ),
411 True,
412 (),
Gabriel Charettea44975052017-08-21 23:14:04413 ),
414 (
415 'base::ScopedMockTimeMessageLoopTaskRunner',
416 (
417 'ScopedMockTimeMessageLoopTaskRunner is deprecated.',
418 ),
419 True,
420 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57421 ),
422 (
423 r'std::regex',
424 (
425 'Using std::regex adds unnecessary binary size to Chrome. Please use',
426 're2::RE2 instead (crbug/755321)',
427 ),
428 True,
429 (),
Francois Doray43670e32017-09-27 12:40:38430 ),
431 (
432 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
433 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
434 (
435 'Use the new API in base/threading/thread_restrictions.h.',
436 ),
437 True,
438 (),
439 ),
[email protected]127f18ec2012-06-16 05:05:59440)
441
wnwenbdc444e2016-05-25 13:44:15442
mlamouria82272622014-09-16 18:45:04443_IPC_ENUM_TRAITS_DEPRECATED = (
444 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
445 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
446
[email protected]127f18ec2012-06-16 05:05:59447
Sean Kau46e29bc2017-08-28 16:31:16448# These paths contain test data and other known invalid JSON files.
449_KNOWN_INVALID_JSON_FILE_PATTERNS = [
450 r'test[\\\/]data[\\\/]',
451 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
452 r'^third_party[\\\/]protobuf[\\\/]',
453]
454
455
[email protected]b00342e7f2013-03-26 16:21:54456_VALID_OS_MACROS = (
457 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08458 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54459 'OS_ANDROID',
460 'OS_BSD',
461 'OS_CAT', # For testing.
462 'OS_CHROMEOS',
463 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37464 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54465 'OS_IOS',
466 'OS_LINUX',
467 'OS_MACOSX',
468 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21469 'OS_NACL_NONSFI',
470 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12471 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54472 'OS_OPENBSD',
473 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37474 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54475 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54476 'OS_WIN',
477)
478
479
agrievef32bcc72016-04-04 14:57:40480_ANDROID_SPECIFIC_PYDEPS_FILES = [
481 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04482 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58483 'build/secondary/third_party/android_platform/'
484 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19485 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40486]
487
wnwenbdc444e2016-05-25 13:44:15488
agrievef32bcc72016-04-04 14:57:40489_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40490]
491
wnwenbdc444e2016-05-25 13:44:15492
agrievef32bcc72016-04-04 14:57:40493_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
494
495
[email protected]55459852011-08-10 15:17:19496def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
497 """Attempts to prevent use of functions intended only for testing in
498 non-testing code. For now this is just a best-effort implementation
499 that ignores header files and may have some false positives. A
500 better implementation would probably need a proper C++ parser.
501 """
502 # We only scan .cc files and the like, as the declaration of
503 # for-testing functions in header files are hard to distinguish from
504 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44505 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19506
jochenc0d4808c2015-07-27 09:25:42507 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19508 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09509 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19510 exclusion_pattern = input_api.re.compile(
511 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
512 base_function_pattern, base_function_pattern))
513
514 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44515 black_list = (_EXCLUDED_PATHS +
516 _TEST_CODE_EXCLUDED_PATHS +
517 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19518 return input_api.FilterSourceFile(
519 affected_file,
520 white_list=(file_inclusion_pattern, ),
521 black_list=black_list)
522
523 problems = []
524 for f in input_api.AffectedSourceFiles(FilterFile):
525 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24526 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03527 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46528 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03529 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19530 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03531 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19532
533 if problems:
[email protected]f7051d52013-04-02 18:31:42534 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03535 else:
536 return []
[email protected]55459852011-08-10 15:17:19537
538
[email protected]10689ca2011-09-02 02:31:54539def _CheckNoIOStreamInHeaders(input_api, output_api):
540 """Checks to make sure no .h files include <iostream>."""
541 files = []
542 pattern = input_api.re.compile(r'^#include\s*<iostream>',
543 input_api.re.MULTILINE)
544 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
545 if not f.LocalPath().endswith('.h'):
546 continue
547 contents = input_api.ReadFile(f)
548 if pattern.search(contents):
549 files.append(f)
550
551 if len(files):
yolandyandaabc6d2016-04-18 18:29:39552 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06553 'Do not #include <iostream> in header files, since it inserts static '
554 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54555 '#include <ostream>. See http://crbug.com/94794',
556 files) ]
557 return []
558
559
[email protected]72df4e782012-06-21 16:28:18560def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52561 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18562 problems = []
563 for f in input_api.AffectedFiles():
564 if (not f.LocalPath().endswith(('.cc', '.mm'))):
565 continue
566
567 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04568 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18569 problems.append(' %s:%d' % (f.LocalPath(), line_num))
570
571 if not problems:
572 return []
573 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
574 '\n'.join(problems))]
575
576
danakj61c1aa22015-10-26 19:55:52577def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57578 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52579 errors = []
580 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
581 input_api.re.MULTILINE)
582 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
583 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
584 continue
585 for lnum, line in f.ChangedContents():
586 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17587 errors.append(output_api.PresubmitError(
588 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57589 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17590 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52591 return errors
592
593
mcasasb7440c282015-02-04 14:52:19594def _FindHistogramNameInLine(histogram_name, line):
595 """Tries to find a histogram name or prefix in a line."""
596 if not "affected-histogram" in line:
597 return histogram_name in line
598 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
599 # the histogram_name.
600 if not '"' in line:
601 return False
602 histogram_prefix = line.split('\"')[1]
603 return histogram_prefix in histogram_name
604
605
606def _CheckUmaHistogramChanges(input_api, output_api):
607 """Check that UMA histogram names in touched lines can still be found in other
608 lines of the patch or in histograms.xml. Note that this check would not catch
609 the reverse: changes in histograms.xml not matched in the code itself."""
610 touched_histograms = []
611 histograms_xml_modifications = []
612 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
613 for f in input_api.AffectedFiles():
614 # If histograms.xml itself is modified, keep the modified lines for later.
615 if f.LocalPath().endswith(('histograms.xml')):
616 histograms_xml_modifications = f.ChangedContents()
617 continue
618 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
619 continue
620 for line_num, line in f.ChangedContents():
621 found = pattern.search(line)
622 if found:
623 touched_histograms.append([found.group(1), f, line_num])
624
625 # Search for the touched histogram names in the local modifications to
626 # histograms.xml, and, if not found, on the base histograms.xml file.
627 unmatched_histograms = []
628 for histogram_info in touched_histograms:
629 histogram_name_found = False
630 for line_num, line in histograms_xml_modifications:
631 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
632 if histogram_name_found:
633 break
634 if not histogram_name_found:
635 unmatched_histograms.append(histogram_info)
636
eromanb90c82e7e32015-04-01 15:13:49637 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19638 problems = []
639 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49640 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19641 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45642 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19643 histogram_name_found = False
644 for line in histograms_xml:
645 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
646 if histogram_name_found:
647 break
648 if not histogram_name_found:
649 problems.append(' [%s:%d] %s' %
650 (f.LocalPath(), line_num, histogram_name))
651
652 if not problems:
653 return []
654 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
655 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49656 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19657
wnwenbdc444e2016-05-25 13:44:15658
yolandyandaabc6d2016-04-18 18:29:39659def _CheckFlakyTestUsage(input_api, output_api):
660 """Check that FlakyTest annotation is our own instead of the android one"""
661 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
662 files = []
663 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
664 if f.LocalPath().endswith('Test.java'):
665 if pattern.search(input_api.ReadFile(f)):
666 files.append(f)
667 if len(files):
668 return [output_api.PresubmitError(
669 'Use org.chromium.base.test.util.FlakyTest instead of '
670 'android.test.FlakyTest',
671 files)]
672 return []
mcasasb7440c282015-02-04 14:52:19673
wnwenbdc444e2016-05-25 13:44:15674
[email protected]8ea5d4b2011-09-13 21:49:22675def _CheckNoNewWStrings(input_api, output_api):
676 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27677 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22678 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20679 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57680 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34681 '/win/' in f.LocalPath() or
682 'chrome_elf' in f.LocalPath() or
683 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20684 continue
[email protected]8ea5d4b2011-09-13 21:49:22685
[email protected]a11dbe9b2012-08-07 01:32:58686 allowWString = False
[email protected]b5c24292011-11-28 14:38:20687 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58688 if 'presubmit: allow wstring' in line:
689 allowWString = True
690 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27691 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58692 allowWString = False
693 else:
694 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22695
[email protected]55463aa62011-10-12 00:48:27696 if not problems:
697 return []
698 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58699 ' If you are calling a cross-platform API that accepts a wstring, '
700 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27701 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22702
703
[email protected]2a8ac9c2011-10-19 17:20:44704def _CheckNoDEPSGIT(input_api, output_api):
705 """Make sure .DEPS.git is never modified manually."""
706 if any(f.LocalPath().endswith('.DEPS.git') for f in
707 input_api.AffectedFiles()):
708 return [output_api.PresubmitError(
709 'Never commit changes to .DEPS.git. This file is maintained by an\n'
710 'automated system based on what\'s in DEPS and your changes will be\n'
711 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34712 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:44713 'for more information')]
714 return []
715
716
tandriief664692014-09-23 14:51:47717def _CheckValidHostsInDEPS(input_api, output_api):
718 """Checks that DEPS file deps are from allowed_hosts."""
719 # Run only if DEPS file has been modified to annoy fewer bystanders.
720 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
721 return []
722 # Outsource work to gclient verify
723 try:
724 input_api.subprocess.check_output(['gclient', 'verify'])
725 return []
726 except input_api.subprocess.CalledProcessError, error:
727 return [output_api.PresubmitError(
728 'DEPS file must have only git dependencies.',
729 long_text=error.output)]
730
731
[email protected]127f18ec2012-06-16 05:05:59732def _CheckNoBannedFunctions(input_api, output_api):
733 """Make sure that banned functions are not used."""
734 warnings = []
735 errors = []
736
wnwenbdc444e2016-05-25 13:44:15737 def IsBlacklisted(affected_file, blacklist):
738 local_path = affected_file.LocalPath()
739 for item in blacklist:
740 if input_api.re.match(item, local_path):
741 return True
742 return False
743
744 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
745 matched = False
746 if func_name[0:1] == '/':
747 regex = func_name[1:]
748 if input_api.re.search(regex, line):
749 matched = True
750 elif func_name in line:
dchenge07de812016-06-20 19:27:17751 matched = True
wnwenbdc444e2016-05-25 13:44:15752 if matched:
dchenge07de812016-06-20 19:27:17753 problems = warnings
wnwenbdc444e2016-05-25 13:44:15754 if error:
dchenge07de812016-06-20 19:27:17755 problems = errors
wnwenbdc444e2016-05-25 13:44:15756 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
757 for message_line in message:
758 problems.append(' %s' % message_line)
759
Eric Stevensona9a980972017-09-23 00:04:41760 file_filter = lambda f: f.LocalPath().endswith(('.java'))
761 for f in input_api.AffectedFiles(file_filter=file_filter):
762 for line_num, line in f.ChangedContents():
763 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
764 CheckForMatch(f, line_num, line, func_name, message, error)
765
[email protected]127f18ec2012-06-16 05:05:59766 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
767 for f in input_api.AffectedFiles(file_filter=file_filter):
768 for line_num, line in f.ChangedContents():
769 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15770 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59771
772 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
773 for f in input_api.AffectedFiles(file_filter=file_filter):
774 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49775 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49776 if IsBlacklisted(f, excluded_paths):
777 continue
wnwenbdc444e2016-05-25 13:44:15778 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59779
780 result = []
781 if (warnings):
782 result.append(output_api.PresubmitPromptWarning(
783 'Banned functions were used.\n' + '\n'.join(warnings)))
784 if (errors):
785 result.append(output_api.PresubmitError(
786 'Banned functions were used.\n' + '\n'.join(errors)))
787 return result
788
789
[email protected]6c063c62012-07-11 19:11:06790def _CheckNoPragmaOnce(input_api, output_api):
791 """Make sure that banned functions are not used."""
792 files = []
793 pattern = input_api.re.compile(r'^#pragma\s+once',
794 input_api.re.MULTILINE)
795 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
796 if not f.LocalPath().endswith('.h'):
797 continue
798 contents = input_api.ReadFile(f)
799 if pattern.search(contents):
800 files.append(f)
801
802 if files:
803 return [output_api.PresubmitError(
804 'Do not use #pragma once in header files.\n'
805 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
806 files)]
807 return []
808
[email protected]127f18ec2012-06-16 05:05:59809
[email protected]e7479052012-09-19 00:26:12810def _CheckNoTrinaryTrueFalse(input_api, output_api):
811 """Checks to make sure we don't introduce use of foo ? true : false."""
812 problems = []
813 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
814 for f in input_api.AffectedFiles():
815 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
816 continue
817
818 for line_num, line in f.ChangedContents():
819 if pattern.match(line):
820 problems.append(' %s:%d' % (f.LocalPath(), line_num))
821
822 if not problems:
823 return []
824 return [output_api.PresubmitPromptWarning(
825 'Please consider avoiding the "? true : false" pattern if possible.\n' +
826 '\n'.join(problems))]
827
828
[email protected]55f9f382012-07-31 11:02:18829def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28830 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18831 change. Breaking - rules is an error, breaking ! rules is a
832 warning.
833 """
mohan.reddyf21db962014-10-16 12:26:47834 import sys
[email protected]55f9f382012-07-31 11:02:18835 # We need to wait until we have an input_api object and use this
836 # roundabout construct to import checkdeps because this file is
837 # eval-ed and thus doesn't have __file__.
838 original_sys_path = sys.path
839 try:
840 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47841 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18842 import checkdeps
843 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:24844 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:28845 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18846 from rules import Rule
847 finally:
848 # Restore sys.path to what it was before.
849 sys.path = original_sys_path
850
851 added_includes = []
rhalavati08acd232017-04-03 07:23:28852 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:24853 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:18854 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28855 if CppChecker.IsCppFile(f.LocalPath()):
856 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08857 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:28858 elif ProtoChecker.IsProtoFile(f.LocalPath()):
859 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08860 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:24861 elif JavaChecker.IsJavaFile(f.LocalPath()):
862 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08863 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18864
[email protected]26385172013-05-09 23:11:35865 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18866
867 error_descriptions = []
868 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28869 error_subjects = set()
870 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18871 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
872 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:08873 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18874 description_with_path = '%s\n %s' % (path, rule_description)
875 if rule_type == Rule.DISALLOW:
876 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28877 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18878 else:
879 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28880 warning_subjects.add("#includes")
881
882 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
883 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:08884 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:28885 description_with_path = '%s\n %s' % (path, rule_description)
886 if rule_type == Rule.DISALLOW:
887 error_descriptions.append(description_with_path)
888 error_subjects.add("imports")
889 else:
890 warning_descriptions.append(description_with_path)
891 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18892
Jinsuk Kim5a092672017-10-24 22:42:24893 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
894 added_java_imports):
Andrew Grieve085f29f2017-11-02 09:14:08895 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:24896 description_with_path = '%s\n %s' % (path, rule_description)
897 if rule_type == Rule.DISALLOW:
898 error_descriptions.append(description_with_path)
899 error_subjects.add("imports")
900 else:
901 warning_descriptions.append(description_with_path)
902 warning_subjects.add("imports")
903
[email protected]55f9f382012-07-31 11:02:18904 results = []
905 if error_descriptions:
906 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28907 'You added one or more %s that violate checkdeps rules.'
908 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18909 error_descriptions))
910 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42911 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28912 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18913 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28914 '%s? See relevant DEPS file(s) for details and contacts.' %
915 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18916 warning_descriptions))
917 return results
918
919
[email protected]fbcafe5a2012-08-08 15:31:22920def _CheckFilePermissions(input_api, output_api):
921 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15922 if input_api.platform == 'win32':
923 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29924 checkperms_tool = input_api.os_path.join(
925 input_api.PresubmitLocalPath(),
926 'tools', 'checkperms', 'checkperms.py')
927 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47928 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22929 for f in input_api.AffectedFiles():
Andrew Grieve933d12e2017-10-30 20:22:53930 args += ['--file', f.AbsoluteLocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11931 try:
932 input_api.subprocess.check_output(args)
933 return []
934 except input_api.subprocess.CalledProcessError as error:
935 return [output_api.PresubmitError(
936 'checkperms.py failed:',
937 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22938
939
robertocn832f5992017-01-04 19:01:30940def _CheckTeamTags(input_api, output_api):
941 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
942 checkteamtags_tool = input_api.os_path.join(
943 input_api.PresubmitLocalPath(),
944 'tools', 'checkteamtags', 'checkteamtags.py')
945 args = [input_api.python_executable, checkteamtags_tool,
946 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22947 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30948 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
949 'OWNERS']
950 try:
951 if files:
952 input_api.subprocess.check_output(args + files)
953 return []
954 except input_api.subprocess.CalledProcessError as error:
955 return [output_api.PresubmitError(
956 'checkteamtags.py failed:',
957 long_text=error.output)]
958
959
[email protected]c8278b32012-10-30 20:35:49960def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
961 """Makes sure we don't include ui/aura/window_property.h
962 in header files.
963 """
964 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
965 errors = []
966 for f in input_api.AffectedFiles():
967 if not f.LocalPath().endswith('.h'):
968 continue
969 for line_num, line in f.ChangedContents():
970 if pattern.match(line):
971 errors.append(' %s:%d' % (f.LocalPath(), line_num))
972
973 results = []
974 if errors:
975 results.append(output_api.PresubmitError(
976 'Header files should not include ui/aura/window_property.h', errors))
977 return results
978
979
[email protected]70ca77752012-11-20 03:45:03980def _CheckForVersionControlConflictsInFile(input_api, f):
981 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
982 errors = []
983 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23984 if f.LocalPath().endswith('.md'):
985 # First-level headers in markdown look a lot like version control
986 # conflict markers. http://daringfireball.net/projects/markdown/basics
987 continue
[email protected]70ca77752012-11-20 03:45:03988 if pattern.match(line):
989 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
990 return errors
991
992
993def _CheckForVersionControlConflicts(input_api, output_api):
994 """Usually this is not intentional and will cause a compile failure."""
995 errors = []
996 for f in input_api.AffectedFiles():
997 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
998
999 results = []
1000 if errors:
1001 results.append(output_api.PresubmitError(
1002 'Version control conflict markers found, please resolve.', errors))
1003 return results
1004
estadee17314a02017-01-12 16:22:161005def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1006 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1007 errors = []
1008 for f in input_api.AffectedFiles():
1009 for line_num, line in f.ChangedContents():
1010 if pattern.search(line):
1011 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1012
1013 results = []
1014 if errors:
1015 results.append(output_api.PresubmitPromptWarning(
1016 'Found Google support URL addressed by answer number. Please replace with '
1017 'a p= identifier instead. See crbug.com/679462\n', errors))
1018 return results
1019
[email protected]70ca77752012-11-20 03:45:031020
[email protected]06e6d0ff2012-12-11 01:36:441021def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1022 def FilterFile(affected_file):
1023 """Filter function for use with input_api.AffectedSourceFiles,
1024 below. This filters out everything except non-test files from
1025 top-level directories that generally speaking should not hard-code
1026 service URLs (e.g. src/android_webview/, src/content/ and others).
1027 """
1028 return input_api.FilterSourceFile(
1029 affected_file,
[email protected]78bb39d62012-12-11 15:11:561030 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441031 black_list=(_EXCLUDED_PATHS +
1032 _TEST_CODE_EXCLUDED_PATHS +
1033 input_api.DEFAULT_BLACK_LIST))
1034
reillyi38965732015-11-16 18:27:331035 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1036 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461037 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1038 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441039 problems = [] # items are (filename, line_number, line)
1040 for f in input_api.AffectedSourceFiles(FilterFile):
1041 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461042 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441043 problems.append((f.LocalPath(), line_num, line))
1044
1045 if problems:
[email protected]f7051d52013-04-02 18:31:421046 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441047 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581048 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441049 [' %s:%d: %s' % (
1050 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031051 else:
1052 return []
[email protected]06e6d0ff2012-12-11 01:36:441053
1054
[email protected]d2530012013-01-25 16:39:271055def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1056 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311057 The native_client_sdk directory is excluded because it has auto-generated PNG
1058 files for documentation.
[email protected]d2530012013-01-25 16:39:271059 """
[email protected]d2530012013-01-25 16:39:271060 errors = []
binji0dcdf342014-12-12 18:32:311061 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1062 black_list = (r'^native_client_sdk[\\\/]',)
1063 file_filter = lambda f: input_api.FilterSourceFile(
1064 f, white_list=white_list, black_list=black_list)
1065 for f in input_api.AffectedFiles(include_deletes=False,
1066 file_filter=file_filter):
1067 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271068
1069 results = []
1070 if errors:
1071 results.append(output_api.PresubmitError(
1072 'The name of PNG files should not have abbreviations. \n'
1073 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1074 'Contact [email protected] if you have questions.', errors))
1075 return results
1076
1077
Daniel Cheng4dcdb6b2017-04-13 08:30:171078def _ExtractAddRulesFromParsedDeps(parsed_deps):
1079 """Extract the rules that add dependencies from a parsed DEPS file.
1080
1081 Args:
1082 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1083 add_rules = set()
1084 add_rules.update([
1085 rule[1:] for rule in parsed_deps.get('include_rules', [])
1086 if rule.startswith('+') or rule.startswith('!')
1087 ])
1088 for specific_file, rules in parsed_deps.get('specific_include_rules',
1089 {}).iteritems():
1090 add_rules.update([
1091 rule[1:] for rule in rules
1092 if rule.startswith('+') or rule.startswith('!')
1093 ])
1094 return add_rules
1095
1096
1097def _ParseDeps(contents):
1098 """Simple helper for parsing DEPS files."""
1099 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171100 class _VarImpl:
1101
1102 def __init__(self, local_scope):
1103 self._local_scope = local_scope
1104
1105 def Lookup(self, var_name):
1106 """Implements the Var syntax."""
1107 try:
1108 return self._local_scope['vars'][var_name]
1109 except KeyError:
1110 raise Exception('Var is not defined: %s' % var_name)
1111
1112 local_scope = {}
1113 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171114 'Var': _VarImpl(local_scope).Lookup,
1115 }
1116 exec contents in global_scope, local_scope
1117 return local_scope
1118
1119
1120def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081121 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411122 a set of DEPS entries that we should look up.
1123
1124 For a directory (rather than a specific filename) we fake a path to
1125 a specific filename by adding /DEPS. This is chosen as a file that
1126 will seldom or never be subject to per-file include_rules.
1127 """
[email protected]2b438d62013-11-14 17:54:141128 # We ignore deps entries on auto-generated directories.
1129 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081130
Daniel Cheng4dcdb6b2017-04-13 08:30:171131 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1132 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1133
1134 added_deps = new_deps.difference(old_deps)
1135
[email protected]2b438d62013-11-14 17:54:141136 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171137 for added_dep in added_deps:
1138 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1139 continue
1140 # Assume that a rule that ends in .h is a rule for a specific file.
1141 if added_dep.endswith('.h'):
1142 results.add(added_dep)
1143 else:
1144 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081145 return results
1146
1147
[email protected]e871964c2013-05-13 14:14:551148def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1149 """When a dependency prefixed with + is added to a DEPS file, we
1150 want to make sure that the change is reviewed by an OWNER of the
1151 target file or directory, to avoid layering violations from being
1152 introduced. This check verifies that this happens.
1153 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171154 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241155
1156 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191157 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241158 for f in input_api.AffectedFiles(include_deletes=False,
1159 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551160 filename = input_api.os_path.basename(f.LocalPath())
1161 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171162 virtual_depended_on_files.update(_CalculateAddedDeps(
1163 input_api.os_path,
1164 '\n'.join(f.OldContents()),
1165 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551166
[email protected]e871964c2013-05-13 14:14:551167 if not virtual_depended_on_files:
1168 return []
1169
1170 if input_api.is_committing:
1171 if input_api.tbr:
1172 return [output_api.PresubmitNotifyResult(
1173 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271174 if input_api.dry_run:
1175 return [output_api.PresubmitNotifyResult(
1176 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551177 if not input_api.change.issue:
1178 return [output_api.PresubmitError(
1179 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401180 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551181 output = output_api.PresubmitError
1182 else:
1183 output = output_api.PresubmitNotifyResult
1184
1185 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501186 owner_email, reviewers = (
1187 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1188 input_api,
1189 owners_db.email_regexp,
1190 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551191
1192 owner_email = owner_email or input_api.change.author_email
1193
[email protected]de4f7d22013-05-23 14:27:461194 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511195 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461196 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551197 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1198 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411199
1200 # We strip the /DEPS part that was added by
1201 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1202 # directory.
1203 def StripDeps(path):
1204 start_deps = path.rfind('/DEPS')
1205 if start_deps != -1:
1206 return path[:start_deps]
1207 else:
1208 return path
1209 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551210 for path in missing_files]
1211
1212 if unapproved_dependencies:
1213 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151214 output('You need LGTM from owners of depends-on paths in DEPS that were '
1215 'modified in this CL:\n %s' %
1216 '\n '.join(sorted(unapproved_dependencies)))]
1217 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1218 output_list.append(output(
1219 'Suggested missing target path OWNERS:\n %s' %
1220 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551221 return output_list
1222
1223 return []
1224
1225
[email protected]85218562013-11-22 07:41:401226def _CheckSpamLogging(input_api, output_api):
1227 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1228 black_list = (_EXCLUDED_PATHS +
1229 _TEST_CODE_EXCLUDED_PATHS +
1230 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501231 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191232 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481233 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461234 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121235 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1236 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581237 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591238 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161239 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031240 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151241 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1242 r"^chromecast[\\\/]",
1243 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481244 r"^components[\\\/]browser_watcher[\\\/]"
1245 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311246 r"^components[\\\/]html_viewer[\\\/]"
1247 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461248 # TODO(peter): Remove this exception. https://crbug.com/534537
1249 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1250 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251251 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1252 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241253 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111254 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151255 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111256 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521257 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501258 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361259 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311260 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131261 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001262 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441263 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451264 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021265 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351266 r"dump_file_system.cc$",
1267 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401268 source_file_filter = lambda x: input_api.FilterSourceFile(
1269 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1270
thomasanderson625d3932017-03-29 07:16:581271 log_info = set([])
1272 printf = set([])
[email protected]85218562013-11-22 07:41:401273
1274 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581275 for _, line in f.ChangedContents():
1276 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1277 log_info.add(f.LocalPath())
1278 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1279 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371280
thomasanderson625d3932017-03-29 07:16:581281 if input_api.re.search(r"\bprintf\(", line):
1282 printf.add(f.LocalPath())
1283 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1284 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401285
1286 if log_info:
1287 return [output_api.PresubmitError(
1288 'These files spam the console log with LOG(INFO):',
1289 items=log_info)]
1290 if printf:
1291 return [output_api.PresubmitError(
1292 'These files spam the console log with printf/fprintf:',
1293 items=printf)]
1294 return []
1295
1296
[email protected]49aa76a2013-12-04 06:59:161297def _CheckForAnonymousVariables(input_api, output_api):
1298 """These types are all expected to hold locks while in scope and
1299 so should never be anonymous (which causes them to be immediately
1300 destroyed)."""
1301 they_who_must_be_named = [
1302 'base::AutoLock',
1303 'base::AutoReset',
1304 'base::AutoUnlock',
1305 'SkAutoAlphaRestore',
1306 'SkAutoBitmapShaderInstall',
1307 'SkAutoBlitterChoose',
1308 'SkAutoBounderCommit',
1309 'SkAutoCallProc',
1310 'SkAutoCanvasRestore',
1311 'SkAutoCommentBlock',
1312 'SkAutoDescriptor',
1313 'SkAutoDisableDirectionCheck',
1314 'SkAutoDisableOvalCheck',
1315 'SkAutoFree',
1316 'SkAutoGlyphCache',
1317 'SkAutoHDC',
1318 'SkAutoLockColors',
1319 'SkAutoLockPixels',
1320 'SkAutoMalloc',
1321 'SkAutoMaskFreeImage',
1322 'SkAutoMutexAcquire',
1323 'SkAutoPathBoundsUpdate',
1324 'SkAutoPDFRelease',
1325 'SkAutoRasterClipValidate',
1326 'SkAutoRef',
1327 'SkAutoTime',
1328 'SkAutoTrace',
1329 'SkAutoUnref',
1330 ]
1331 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1332 # bad: base::AutoLock(lock.get());
1333 # not bad: base::AutoLock lock(lock.get());
1334 bad_pattern = input_api.re.compile(anonymous)
1335 # good: new base::AutoLock(lock.get())
1336 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1337 errors = []
1338
1339 for f in input_api.AffectedFiles():
1340 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1341 continue
1342 for linenum, line in f.ChangedContents():
1343 if bad_pattern.search(line) and not good_pattern.search(line):
1344 errors.append('%s:%d' % (f.LocalPath(), linenum))
1345
1346 if errors:
1347 return [output_api.PresubmitError(
1348 'These lines create anonymous variables that need to be named:',
1349 items=errors)]
1350 return []
1351
1352
[email protected]999261d2014-03-03 20:08:081353def _CheckUserActionUpdate(input_api, output_api):
1354 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521355 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081356 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521357 # If actions.xml is already included in the changelist, the PRESUBMIT
1358 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081359 return []
1360
[email protected]999261d2014-03-03 20:08:081361 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1362 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521363 current_actions = None
[email protected]999261d2014-03-03 20:08:081364 for f in input_api.AffectedFiles(file_filter=file_filter):
1365 for line_num, line in f.ChangedContents():
1366 match = input_api.re.search(action_re, line)
1367 if match:
[email protected]2f92dec2014-03-07 19:21:521368 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1369 # loaded only once.
1370 if not current_actions:
1371 with open('tools/metrics/actions/actions.xml') as actions_f:
1372 current_actions = actions_f.read()
1373 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081374 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521375 action = 'name="{0}"'.format(action_name)
1376 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081377 return [output_api.PresubmitPromptWarning(
1378 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521379 'tools/metrics/actions/actions.xml. Please run '
1380 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081381 % (f.LocalPath(), line_num, action_name))]
1382 return []
1383
1384
Daniel Cheng13ca61a882017-08-25 15:11:251385def _ImportJSONCommentEater(input_api):
1386 import sys
1387 sys.path = sys.path + [input_api.os_path.join(
1388 input_api.PresubmitLocalPath(),
1389 'tools', 'json_comment_eater')]
1390 import json_comment_eater
1391 return json_comment_eater
1392
1393
[email protected]99171a92014-06-03 08:44:471394def _GetJSONParseError(input_api, filename, eat_comments=True):
1395 try:
1396 contents = input_api.ReadFile(filename)
1397 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251398 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131399 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471400
1401 input_api.json.loads(contents)
1402 except ValueError as e:
1403 return e
1404 return None
1405
1406
1407def _GetIDLParseError(input_api, filename):
1408 try:
1409 contents = input_api.ReadFile(filename)
1410 idl_schema = input_api.os_path.join(
1411 input_api.PresubmitLocalPath(),
1412 'tools', 'json_schema_compiler', 'idl_schema.py')
1413 process = input_api.subprocess.Popen(
1414 [input_api.python_executable, idl_schema],
1415 stdin=input_api.subprocess.PIPE,
1416 stdout=input_api.subprocess.PIPE,
1417 stderr=input_api.subprocess.PIPE,
1418 universal_newlines=True)
1419 (_, error) = process.communicate(input=contents)
1420 return error or None
1421 except ValueError as e:
1422 return e
1423
1424
1425def _CheckParseErrors(input_api, output_api):
1426 """Check that IDL and JSON files do not contain syntax errors."""
1427 actions = {
1428 '.idl': _GetIDLParseError,
1429 '.json': _GetJSONParseError,
1430 }
[email protected]99171a92014-06-03 08:44:471431 # Most JSON files are preprocessed and support comments, but these do not.
1432 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491433 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471434 ]
1435 # Only run IDL checker on files in these directories.
1436 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491437 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1438 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471439 ]
1440
1441 def get_action(affected_file):
1442 filename = affected_file.LocalPath()
1443 return actions.get(input_api.os_path.splitext(filename)[1])
1444
[email protected]99171a92014-06-03 08:44:471445 def FilterFile(affected_file):
1446 action = get_action(affected_file)
1447 if not action:
1448 return False
1449 path = affected_file.LocalPath()
1450
Sean Kau46e29bc2017-08-28 16:31:161451 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471452 return False
1453
1454 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161455 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471456 return False
1457 return True
1458
1459 results = []
1460 for affected_file in input_api.AffectedFiles(
1461 file_filter=FilterFile, include_deletes=False):
1462 action = get_action(affected_file)
1463 kwargs = {}
1464 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161465 _MatchesFile(input_api, json_no_comments_patterns,
1466 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471467 kwargs['eat_comments'] = False
1468 parse_error = action(input_api,
1469 affected_file.AbsoluteLocalPath(),
1470 **kwargs)
1471 if parse_error:
1472 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1473 (affected_file.LocalPath(), parse_error)))
1474 return results
1475
1476
[email protected]760deea2013-12-10 19:33:491477def _CheckJavaStyle(input_api, output_api):
1478 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471479 import sys
[email protected]760deea2013-12-10 19:33:491480 original_sys_path = sys.path
1481 try:
1482 sys.path = sys.path + [input_api.os_path.join(
1483 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1484 import checkstyle
1485 finally:
1486 # Restore sys.path to what it was before.
1487 sys.path = original_sys_path
1488
1489 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091490 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511491 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491492
1493
Sean Kau46e29bc2017-08-28 16:31:161494def _MatchesFile(input_api, patterns, path):
1495 for pattern in patterns:
1496 if input_api.re.search(pattern, path):
1497 return True
1498 return False
1499
1500
dchenge07de812016-06-20 19:27:171501def _CheckIpcOwners(input_api, output_api):
1502 """Checks that affected files involving IPC have an IPC OWNERS rule.
1503
1504 Whether or not a file affects IPC is determined by a simple whitelist of
1505 filename patterns."""
1506 file_patterns = [
palmerb19a0932017-01-24 04:00:311507 # Legacy IPC:
dchenge07de812016-06-20 19:27:171508 '*_messages.cc',
1509 '*_messages*.h',
1510 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311511 # Mojo IPC:
dchenge07de812016-06-20 19:27:171512 '*.mojom',
1513 '*_struct_traits*.*',
1514 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311515 '*.typemap',
1516 # Android native IPC:
1517 '*.aidl',
1518 # Blink uses a different file naming convention:
1519 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171520 '*StructTraits*.*',
1521 '*TypeConverter*.*',
1522 ]
1523
scottmg7a6ed5ba2016-11-04 18:22:041524 # These third_party directories do not contain IPCs, but contain files
1525 # matching the above patterns, which trigger false positives.
1526 exclude_paths = [
1527 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291528 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041529 ]
1530
dchenge07de812016-06-20 19:27:171531 # Dictionary mapping an OWNERS file path to Patterns.
1532 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1533 # rules ) to a PatternEntry.
1534 # PatternEntry is a dictionary with two keys:
1535 # - 'files': the files that are matched by this pattern
1536 # - 'rules': the per-file rules needed for this pattern
1537 # For example, if we expect OWNERS file to contain rules for *.mojom and
1538 # *_struct_traits*.*, Patterns might look like this:
1539 # {
1540 # '*.mojom': {
1541 # 'files': ...,
1542 # 'rules': [
1543 # 'per-file *.mojom=set noparent',
1544 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1545 # ],
1546 # },
1547 # '*_struct_traits*.*': {
1548 # 'files': ...,
1549 # 'rules': [
1550 # 'per-file *_struct_traits*.*=set noparent',
1551 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1552 # ],
1553 # },
1554 # }
1555 to_check = {}
1556
Daniel Cheng13ca61a882017-08-25 15:11:251557 def AddPatternToCheck(input_file, pattern):
1558 owners_file = input_api.os_path.join(
1559 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1560 if owners_file not in to_check:
1561 to_check[owners_file] = {}
1562 if pattern not in to_check[owners_file]:
1563 to_check[owners_file][pattern] = {
1564 'files': [],
1565 'rules': [
1566 'per-file %s=set noparent' % pattern,
1567 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1568 ]
1569 }
1570 to_check[owners_file][pattern]['files'].append(f)
1571
dchenge07de812016-06-20 19:27:171572 # Iterate through the affected files to see what we actually need to check
1573 # for. We should only nag patch authors about per-file rules if a file in that
1574 # directory would match that pattern. If a directory only contains *.mojom
1575 # files and no *_messages*.h files, we should only nag about rules for
1576 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251577 for f in input_api.AffectedFiles(include_deletes=False):
1578 # Manifest files don't have a strong naming convention. Instead, scan
1579 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161580 if (f.LocalPath().endswith('.json') and
1581 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1582 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251583 json_comment_eater = _ImportJSONCommentEater(input_api)
1584 mostly_json_lines = '\n'.join(f.NewContents())
1585 # Comments aren't allowed in strict JSON, so filter them out.
1586 json_lines = json_comment_eater.Nom(mostly_json_lines)
1587 json_content = input_api.json.loads(json_lines)
1588 if 'interface_provider_specs' in json_content:
1589 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171590 for pattern in file_patterns:
1591 if input_api.fnmatch.fnmatch(
1592 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041593 skip = False
1594 for exclude in exclude_paths:
1595 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1596 skip = True
1597 break
1598 if skip:
1599 continue
Daniel Cheng13ca61a882017-08-25 15:11:251600 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171601 break
1602
1603 # Now go through the OWNERS files we collected, filtering out rules that are
1604 # already present in that OWNERS file.
1605 for owners_file, patterns in to_check.iteritems():
1606 try:
1607 with file(owners_file) as f:
1608 lines = set(f.read().splitlines())
1609 for entry in patterns.itervalues():
1610 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1611 ]
1612 except IOError:
1613 # No OWNERS file, so all the rules are definitely missing.
1614 continue
1615
1616 # All the remaining lines weren't found in OWNERS files, so emit an error.
1617 errors = []
1618 for owners_file, patterns in to_check.iteritems():
1619 missing_lines = []
1620 files = []
1621 for pattern, entry in patterns.iteritems():
1622 missing_lines.extend(entry['rules'])
1623 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1624 if missing_lines:
1625 errors.append(
Daniel Cheng52111692017-06-14 08:00:591626 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171627 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1628
1629 results = []
1630 if errors:
vabrf5ce3bf92016-07-11 14:52:411631 if input_api.is_committing:
1632 output = output_api.PresubmitError
1633 else:
1634 output = output_api.PresubmitPromptWarning
1635 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591636 'Found OWNERS files that need to be updated for IPC security ' +
1637 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171638 long_text='\n\n'.join(errors)))
1639
1640 return results
1641
1642
jbriance9e12f162016-11-25 07:57:501643def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311644 """Checks that added or removed lines in non third party affected
1645 header files do not lead to new useless class or struct forward
1646 declaration.
jbriance9e12f162016-11-25 07:57:501647 """
1648 results = []
1649 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1650 input_api.re.MULTILINE)
1651 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1652 input_api.re.MULTILINE)
1653 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311654 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191655 not f.LocalPath().startswith('third_party/blink') and
1656 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311657 not f.LocalPath().startswith('third_party/WebKit') and
1658 not f.LocalPath().startswith('third_party\\WebKit')):
1659 continue
1660
jbriance9e12f162016-11-25 07:57:501661 if not f.LocalPath().endswith('.h'):
1662 continue
1663
1664 contents = input_api.ReadFile(f)
1665 fwd_decls = input_api.re.findall(class_pattern, contents)
1666 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1667
1668 useless_fwd_decls = []
1669 for decl in fwd_decls:
1670 count = sum(1 for _ in input_api.re.finditer(
1671 r'\b%s\b' % input_api.re.escape(decl), contents))
1672 if count == 1:
1673 useless_fwd_decls.append(decl)
1674
1675 if not useless_fwd_decls:
1676 continue
1677
1678 for line in f.GenerateScmDiff().splitlines():
1679 if (line.startswith('-') and not line.startswith('--') or
1680 line.startswith('+') and not line.startswith('++')):
1681 for decl in useless_fwd_decls:
1682 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1683 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241684 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501685 (f.LocalPath(), decl)))
1686 useless_fwd_decls.remove(decl)
1687
1688 return results
1689
1690
dskiba88634f4e2015-08-14 23:03:291691def _CheckAndroidToastUsage(input_api, output_api):
1692 """Checks that code uses org.chromium.ui.widget.Toast instead of
1693 android.widget.Toast (Chromium Toast doesn't force hardware
1694 acceleration on low-end devices, saving memory).
1695 """
1696 toast_import_pattern = input_api.re.compile(
1697 r'^import android\.widget\.Toast;$')
1698
1699 errors = []
1700
1701 sources = lambda affected_file: input_api.FilterSourceFile(
1702 affected_file,
1703 black_list=(_EXCLUDED_PATHS +
1704 _TEST_CODE_EXCLUDED_PATHS +
1705 input_api.DEFAULT_BLACK_LIST +
1706 (r'^chromecast[\\\/].*',
1707 r'^remoting[\\\/].*')),
1708 white_list=(r'.*\.java$',))
1709
1710 for f in input_api.AffectedSourceFiles(sources):
1711 for line_num, line in f.ChangedContents():
1712 if toast_import_pattern.search(line):
1713 errors.append("%s:%d" % (f.LocalPath(), line_num))
1714
1715 results = []
1716
1717 if errors:
1718 results.append(output_api.PresubmitError(
1719 'android.widget.Toast usage is detected. Android toasts use hardware'
1720 ' acceleration, and can be\ncostly on low-end devices. Please use'
1721 ' org.chromium.ui.widget.Toast instead.\n'
1722 'Contact [email protected] if you have any questions.',
1723 errors))
1724
1725 return results
1726
1727
dgnaa68d5e2015-06-10 10:08:221728def _CheckAndroidCrLogUsage(input_api, output_api):
1729 """Checks that new logs using org.chromium.base.Log:
1730 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511731 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221732 """
pkotwicza1dd0b002016-05-16 14:41:041733
torne89540622017-03-24 19:41:301734 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041735 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301736 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041737 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301738 # WebView license viewer code cannot depend on //base; used in stub APK.
1739 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1740 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041741 ]
1742
dgnaa68d5e2015-06-10 10:08:221743 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121744 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1745 class_in_base_pattern = input_api.re.compile(
1746 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1747 has_some_log_import_pattern = input_api.re.compile(
1748 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221749 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121750 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221751 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511752 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221753 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221754
Vincent Scheib16d7b272015-09-15 18:09:071755 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221756 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041757 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1758 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121759
dgnaa68d5e2015-06-10 10:08:221760 tag_decl_errors = []
1761 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121762 tag_errors = []
dgn38736db2015-09-18 19:20:511763 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121764 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221765
1766 for f in input_api.AffectedSourceFiles(sources):
1767 file_content = input_api.ReadFile(f)
1768 has_modified_logs = False
1769
1770 # Per line checks
dgn87d9fb62015-06-12 09:15:121771 if (cr_log_import_pattern.search(file_content) or
1772 (class_in_base_pattern.search(file_content) and
1773 not has_some_log_import_pattern.search(file_content))):
1774 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221775 for line_num, line in f.ChangedContents():
1776
1777 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121778 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221779 if match:
1780 has_modified_logs = True
1781
1782 # Make sure it uses "TAG"
1783 if not match.group('tag') == 'TAG':
1784 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121785 else:
1786 # Report non cr Log function calls in changed lines
1787 for line_num, line in f.ChangedContents():
1788 if log_call_pattern.search(line):
1789 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221790
1791 # Per file checks
1792 if has_modified_logs:
1793 # Make sure the tag is using the "cr" prefix and is not too long
1794 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511795 tag_name = match.group('name') if match else None
1796 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221797 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511798 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221799 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511800 elif '.' in tag_name:
1801 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221802
1803 results = []
1804 if tag_decl_errors:
1805 results.append(output_api.PresubmitPromptWarning(
1806 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511807 '"private static final String TAG = "<package tag>".\n'
1808 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221809 tag_decl_errors))
1810
1811 if tag_length_errors:
1812 results.append(output_api.PresubmitError(
1813 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511814 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221815 tag_length_errors))
1816
1817 if tag_errors:
1818 results.append(output_api.PresubmitPromptWarning(
1819 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1820 tag_errors))
1821
dgn87d9fb62015-06-12 09:15:121822 if util_log_errors:
dgn4401aa52015-04-29 16:26:171823 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121824 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1825 util_log_errors))
1826
dgn38736db2015-09-18 19:20:511827 if tag_with_dot_errors:
1828 results.append(output_api.PresubmitPromptWarning(
1829 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1830 tag_with_dot_errors))
1831
dgn4401aa52015-04-29 16:26:171832 return results
1833
1834
Yoland Yanb92fa522017-08-28 17:37:061835def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1836 """Checks that junit.framework.* is no longer used."""
1837 deprecated_junit_framework_pattern = input_api.re.compile(
1838 r'^import junit\.framework\..*;',
1839 input_api.re.MULTILINE)
1840 sources = lambda x: input_api.FilterSourceFile(
1841 x, white_list=(r'.*\.java$',), black_list=None)
1842 errors = []
1843 for f in input_api.AffectedFiles(sources):
1844 for line_num, line in f.ChangedContents():
1845 if deprecated_junit_framework_pattern.search(line):
1846 errors.append("%s:%d" % (f.LocalPath(), line_num))
1847
1848 results = []
1849 if errors:
1850 results.append(output_api.PresubmitError(
1851 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1852 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1853 ' if you have any question.', errors))
1854 return results
1855
1856
1857def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1858 """Checks that if new Java test classes have inheritance.
1859 Either the new test class is JUnit3 test or it is a JUnit4 test class
1860 with a base class, either case is undesirable.
1861 """
1862 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1863
1864 sources = lambda x: input_api.FilterSourceFile(
1865 x, white_list=(r'.*Test\.java$',), black_list=None)
1866 errors = []
1867 for f in input_api.AffectedFiles(sources):
1868 if not f.OldContents():
1869 class_declaration_start_flag = False
1870 for line_num, line in f.ChangedContents():
1871 if class_declaration_pattern.search(line):
1872 class_declaration_start_flag = True
1873 if class_declaration_start_flag and ' extends ' in line:
1874 errors.append('%s:%d' % (f.LocalPath(), line_num))
1875 if '{' in line:
1876 class_declaration_start_flag = False
1877
1878 results = []
1879 if errors:
1880 results.append(output_api.PresubmitPromptWarning(
1881 'The newly created files include Test classes that inherits from base'
1882 ' class. Please do not use inheritance in JUnit4 tests or add new'
1883 ' JUnit3 tests. Contact [email protected] if you have any'
1884 ' questions.', errors))
1885 return results
1886
yolandyan45001472016-12-21 21:12:421887def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1888 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1889 deprecated_annotation_import_pattern = input_api.re.compile(
1890 r'^import android\.test\.suitebuilder\.annotation\..*;',
1891 input_api.re.MULTILINE)
1892 sources = lambda x: input_api.FilterSourceFile(
1893 x, white_list=(r'.*\.java$',), black_list=None)
1894 errors = []
1895 for f in input_api.AffectedFiles(sources):
1896 for line_num, line in f.ChangedContents():
1897 if deprecated_annotation_import_pattern.search(line):
1898 errors.append("%s:%d" % (f.LocalPath(), line_num))
1899
1900 results = []
1901 if errors:
1902 results.append(output_api.PresubmitError(
1903 'Annotations in android.test.suitebuilder.annotation have been'
1904 ' deprecated since API level 24. Please use android.support.test.filters'
1905 ' from //third_party/android_support_test_runner:runner_java instead.'
1906 ' Contact [email protected] if you have any questions.', errors))
1907 return results
1908
1909
agrieve7b6479d82015-10-07 14:24:221910def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1911 """Checks if MDPI assets are placed in a correct directory."""
1912 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1913 ('/res/drawable/' in f.LocalPath() or
1914 '/res/drawable-ldrtl/' in f.LocalPath()))
1915 errors = []
1916 for f in input_api.AffectedFiles(include_deletes=False,
1917 file_filter=file_filter):
1918 errors.append(' %s' % f.LocalPath())
1919
1920 results = []
1921 if errors:
1922 results.append(output_api.PresubmitError(
1923 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1924 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1925 '/res/drawable-ldrtl/.\n'
1926 'Contact [email protected] if you have questions.', errors))
1927 return results
1928
1929
Nate Fischer535972b2017-09-16 01:06:181930def _CheckAndroidWebkitImports(input_api, output_api):
1931 """Checks that code uses org.chromium.base.Callback instead of
1932 android.widget.ValueCallback except in the WebView glue layer.
1933 """
1934 valuecallback_import_pattern = input_api.re.compile(
1935 r'^import android\.webkit\.ValueCallback;$')
1936
1937 errors = []
1938
1939 sources = lambda affected_file: input_api.FilterSourceFile(
1940 affected_file,
1941 black_list=(_EXCLUDED_PATHS +
1942 _TEST_CODE_EXCLUDED_PATHS +
1943 input_api.DEFAULT_BLACK_LIST +
1944 (r'^android_webview[\\\/]glue[\\\/].*',)),
1945 white_list=(r'.*\.java$',))
1946
1947 for f in input_api.AffectedSourceFiles(sources):
1948 for line_num, line in f.ChangedContents():
1949 if valuecallback_import_pattern.search(line):
1950 errors.append("%s:%d" % (f.LocalPath(), line_num))
1951
1952 results = []
1953
1954 if errors:
1955 results.append(output_api.PresubmitError(
1956 'android.webkit.ValueCallback usage is detected outside of the glue'
1957 ' layer. To stay compatible with the support library, android.webkit.*'
1958 ' classes should only be used inside the glue layer and'
1959 ' org.chromium.base.Callback should be used instead.',
1960 errors))
1961
1962 return results
1963
1964
agrievef32bcc72016-04-04 14:57:401965class PydepsChecker(object):
1966 def __init__(self, input_api, pydeps_files):
1967 self._file_cache = {}
1968 self._input_api = input_api
1969 self._pydeps_files = pydeps_files
1970
1971 def _LoadFile(self, path):
1972 """Returns the list of paths within a .pydeps file relative to //."""
1973 if path not in self._file_cache:
1974 with open(path) as f:
1975 self._file_cache[path] = f.read()
1976 return self._file_cache[path]
1977
1978 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1979 """Returns an interable of paths within the .pydep, relativized to //."""
1980 os_path = self._input_api.os_path
1981 pydeps_dir = os_path.dirname(pydeps_path)
1982 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1983 if not l.startswith('*'))
1984 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1985
1986 def _CreateFilesToPydepsMap(self):
1987 """Returns a map of local_path -> list_of_pydeps."""
1988 ret = {}
1989 for pydep_local_path in self._pydeps_files:
1990 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1991 ret.setdefault(path, []).append(pydep_local_path)
1992 return ret
1993
1994 def ComputeAffectedPydeps(self):
1995 """Returns an iterable of .pydeps files that might need regenerating."""
1996 affected_pydeps = set()
1997 file_to_pydeps_map = None
1998 for f in self._input_api.AffectedFiles(include_deletes=True):
1999 local_path = f.LocalPath()
2000 if local_path == 'DEPS':
2001 return self._pydeps_files
2002 elif local_path.endswith('.pydeps'):
2003 if local_path in self._pydeps_files:
2004 affected_pydeps.add(local_path)
2005 elif local_path.endswith('.py'):
2006 if file_to_pydeps_map is None:
2007 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2008 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2009 return affected_pydeps
2010
2011 def DetermineIfStale(self, pydeps_path):
2012 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412013 import difflib
agrievef32bcc72016-04-04 14:57:402014 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2015 cmd = old_pydeps_data[1][1:].strip()
John Budorickab2fa102017-10-06 16:59:492016 env = {
2017 'PYTHONDONTWRITEBYTECODE': '1'
2018 }
agrievef32bcc72016-04-04 14:57:402019 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorickab2fa102017-10-06 16:59:492020 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412021 old_contents = old_pydeps_data[2:]
2022 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402023 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412024 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402025
2026
2027def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2028 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:002029 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:282030 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
2031 # Mac, so skip it on other platforms.
2032 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002033 return []
agrievef32bcc72016-04-04 14:57:402034 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
2035 is_android = input_api.os_path.exists('third_party/android_tools')
2036 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2037 results = []
2038 # First, check for new / deleted .pydeps.
2039 for f in input_api.AffectedFiles(include_deletes=True):
2040 if f.LocalPath().endswith('.pydeps'):
2041 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2042 results.append(output_api.PresubmitError(
2043 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2044 'remove %s' % f.LocalPath()))
2045 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2046 results.append(output_api.PresubmitError(
2047 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2048 'include %s' % f.LocalPath()))
2049
2050 if results:
2051 return results
2052
2053 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2054
2055 for pydep_path in checker.ComputeAffectedPydeps():
2056 try:
phajdan.jr0d9878552016-11-04 10:49:412057 result = checker.DetermineIfStale(pydep_path)
2058 if result:
2059 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402060 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412061 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2062 'To regenerate, run:\n\n %s' %
2063 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402064 except input_api.subprocess.CalledProcessError as error:
2065 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2066 long_text=error.output)]
2067
2068 return results
2069
2070
glidere61efad2015-02-18 17:39:432071def _CheckSingletonInHeaders(input_api, output_api):
2072 """Checks to make sure no header files have |Singleton<|."""
2073 def FileFilter(affected_file):
2074 # It's ok for base/memory/singleton.h to have |Singleton<|.
2075 black_list = (_EXCLUDED_PATHS +
2076 input_api.DEFAULT_BLACK_LIST +
2077 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2078 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2079
sergeyu34d21222015-09-16 00:11:442080 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432081 files = []
2082 for f in input_api.AffectedSourceFiles(FileFilter):
2083 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2084 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2085 contents = input_api.ReadFile(f)
2086 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242087 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432088 pattern.search(line)):
2089 files.append(f)
2090 break
2091
2092 if files:
yolandyandaabc6d2016-04-18 18:29:392093 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442094 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432095 'Please move them to an appropriate source file so that the ' +
2096 'template gets instantiated in a single compilation unit.',
2097 files) ]
2098 return []
2099
2100
[email protected]fd20b902014-05-09 02:14:532101_DEPRECATED_CSS = [
2102 # Values
2103 ( "-webkit-box", "flex" ),
2104 ( "-webkit-inline-box", "inline-flex" ),
2105 ( "-webkit-flex", "flex" ),
2106 ( "-webkit-inline-flex", "inline-flex" ),
2107 ( "-webkit-min-content", "min-content" ),
2108 ( "-webkit-max-content", "max-content" ),
2109
2110 # Properties
2111 ( "-webkit-background-clip", "background-clip" ),
2112 ( "-webkit-background-origin", "background-origin" ),
2113 ( "-webkit-background-size", "background-size" ),
2114 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442115 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532116
2117 # Functions
2118 ( "-webkit-gradient", "gradient" ),
2119 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2120 ( "-webkit-linear-gradient", "linear-gradient" ),
2121 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2122 ( "-webkit-radial-gradient", "radial-gradient" ),
2123 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2124]
2125
dbeam1ec68ac2016-12-15 05:22:242126def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532127 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252128 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342129 documentation and iOS CSS for dom distiller
2130 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252131 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532132 results = []
dbeam070cfe62014-10-22 06:44:022133 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252134 black_list = (_EXCLUDED_PATHS +
2135 _TEST_CODE_EXCLUDED_PATHS +
2136 input_api.DEFAULT_BLACK_LIST +
2137 (r"^chrome/common/extensions/docs",
2138 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342139 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442140 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252141 r"^native_client_sdk"))
2142 file_filter = lambda f: input_api.FilterSourceFile(
2143 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532144 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2145 for line_num, line in fpath.ChangedContents():
2146 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022147 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532148 results.append(output_api.PresubmitError(
2149 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2150 (fpath.LocalPath(), line_num, deprecated_value, value)))
2151 return results
2152
mohan.reddyf21db962014-10-16 12:26:472153
dbeam070cfe62014-10-22 06:44:022154_DEPRECATED_JS = [
2155 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2156 ( "__defineGetter__", "Object.defineProperty" ),
2157 ( "__defineSetter__", "Object.defineProperty" ),
2158]
2159
dbeam1ec68ac2016-12-15 05:22:242160def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022161 """Make sure that we don't use deprecated JS in Chrome code."""
2162 results = []
2163 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2164 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2165 input_api.DEFAULT_BLACK_LIST)
2166 file_filter = lambda f: input_api.FilterSourceFile(
2167 f, white_list=file_inclusion_pattern, black_list=black_list)
2168 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2169 for lnum, line in fpath.ChangedContents():
2170 for (deprecated, replacement) in _DEPRECATED_JS:
2171 if deprecated in line:
2172 results.append(output_api.PresubmitError(
2173 "%s:%d: Use of deprecated JS %s, use %s instead" %
2174 (fpath.LocalPath(), lnum, deprecated, replacement)))
2175 return results
2176
dpapadd651231d82017-07-21 02:44:472177def _CheckForRiskyJsArrowFunction(line_number, line):
2178 if ' => ' in line:
2179 return "line %d, is using an => (arrow) function\n %s\n" % (
2180 line_number, line)
2181 return ''
2182
2183def _CheckForRiskyJsConstLet(input_api, line_number, line):
2184 if input_api.re.match('^\s*(const|let)\s', line):
2185 return "line %d, is using const/let keyword\n %s\n" % (
2186 line_number, line)
2187 return ''
dbeam070cfe62014-10-22 06:44:022188
dbeam1ec68ac2016-12-15 05:22:242189def _CheckForRiskyJsFeatures(input_api, output_api):
2190 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002191 # 'ui/webui/resources/cr_components are not allowed on ios'
2192 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572193 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002194 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472195 results = []
dbeam1ec68ac2016-12-15 05:22:242196 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472197 arrow_error_lines = []
2198 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242199 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472200 arrow_error_lines += filter(None, [
2201 _CheckForRiskyJsArrowFunction(lnum, line),
2202 ])
dbeam1ec68ac2016-12-15 05:22:242203
dpapadd651231d82017-07-21 02:44:472204 const_let_error_lines += filter(None, [
2205 _CheckForRiskyJsConstLet(input_api, lnum, line),
2206 ])
dbeam1ec68ac2016-12-15 05:22:242207
dpapadd651231d82017-07-21 02:44:472208 if arrow_error_lines:
2209 arrow_error_lines = map(
2210 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2211 results.append(
2212 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2213"""
2214Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242215%s
2216Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2217https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472218""" % f.LocalPath()
2219 ])))
dbeam1ec68ac2016-12-15 05:22:242220
dpapadd651231d82017-07-21 02:44:472221 if const_let_error_lines:
2222 const_let_error_lines = map(
2223 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2224 results.append(
2225 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2226"""
2227Use of const/let keywords detected in:
2228%s
2229Please ensure your code does not run on iOS9 because const/let is not fully
2230supported.
2231https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2232https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2233""" % f.LocalPath()
2234 ])))
2235
2236 return results
dbeam1ec68ac2016-12-15 05:22:242237
rlanday6802cf632017-05-30 17:48:362238def _CheckForRelativeIncludes(input_api, output_api):
2239 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2240 import sys
2241 original_sys_path = sys.path
2242 try:
2243 sys.path = sys.path + [input_api.os_path.join(
2244 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2245 from cpp_checker import CppChecker
2246 finally:
2247 # Restore sys.path to what it was before.
2248 sys.path = original_sys_path
2249
2250 bad_files = {}
2251 for f in input_api.AffectedFiles(include_deletes=False):
2252 if (f.LocalPath().startswith('third_party') and
2253 not f.LocalPath().startswith('third_party/WebKit') and
2254 not f.LocalPath().startswith('third_party\\WebKit')):
2255 continue
2256
2257 if not CppChecker.IsCppFile(f.LocalPath()):
2258 continue
2259
2260 relative_includes = [line for line_num, line in f.ChangedContents()
2261 if "#include" in line and "../" in line]
2262 if not relative_includes:
2263 continue
2264 bad_files[f.LocalPath()] = relative_includes
2265
2266 if not bad_files:
2267 return []
2268
2269 error_descriptions = []
2270 for file_path, bad_lines in bad_files.iteritems():
2271 error_description = file_path
2272 for line in bad_lines:
2273 error_description += '\n ' + line
2274 error_descriptions.append(error_description)
2275
2276 results = []
2277 results.append(output_api.PresubmitError(
2278 'You added one or more relative #include paths (including "../").\n'
2279 'These shouldn\'t be used because they can be used to include headers\n'
2280 'from code that\'s not correctly specified as a dependency in the\n'
2281 'relevant BUILD.gn file(s).',
2282 error_descriptions))
2283
2284 return results
2285
Takeshi Yoshinoe387aa32017-08-02 13:16:132286
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202287def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2288 if not isinstance(key, ast.Str):
2289 return 'Key at line %d must be a string literal' % key.lineno
2290 if not isinstance(value, ast.Dict):
2291 return 'Value at line %d must be a dict' % value.lineno
2292 if len(value.keys) != 1:
2293 return 'Dict at line %d must have single entry' % value.lineno
2294 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2295 return (
2296 'Entry at line %d must have a string literal \'filepath\' as key' %
2297 value.lineno)
2298 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132299
Takeshi Yoshinoe387aa32017-08-02 13:16:132300
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202301def _CheckWatchlistsEntrySyntax(key, value, ast):
2302 if not isinstance(key, ast.Str):
2303 return 'Key at line %d must be a string literal' % key.lineno
2304 if not isinstance(value, ast.List):
2305 return 'Value at line %d must be a list' % value.lineno
2306 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132307
Takeshi Yoshinoe387aa32017-08-02 13:16:132308
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202309def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2310 mismatch_template = (
2311 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2312 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132313
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202314 i = 0
2315 last_key = ''
2316 while True:
2317 if i >= len(wd_dict.keys):
2318 if i >= len(w_dict.keys):
2319 return None
2320 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2321 elif i >= len(w_dict.keys):
2322 return (
2323 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132324
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202325 wd_key = wd_dict.keys[i]
2326 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132327
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202328 result = _CheckWatchlistDefinitionsEntrySyntax(
2329 wd_key, wd_dict.values[i], ast)
2330 if result is not None:
2331 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132332
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202333 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2334 if result is not None:
2335 return 'Bad entry in WATCHLISTS dict: %s' % result
2336
2337 if wd_key.s != w_key.s:
2338 return mismatch_template % (
2339 '%s at line %d' % (wd_key.s, wd_key.lineno),
2340 '%s at line %d' % (w_key.s, w_key.lineno))
2341
2342 if wd_key.s < last_key:
2343 return (
2344 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2345 (wd_key.lineno, w_key.lineno))
2346 last_key = wd_key.s
2347
2348 i = i + 1
2349
2350
2351def _CheckWATCHLISTSSyntax(expression, ast):
2352 if not isinstance(expression, ast.Expression):
2353 return 'WATCHLISTS file must contain a valid expression'
2354 dictionary = expression.body
2355 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2356 return 'WATCHLISTS file must have single dict with exactly two entries'
2357
2358 first_key = dictionary.keys[0]
2359 first_value = dictionary.values[0]
2360 second_key = dictionary.keys[1]
2361 second_value = dictionary.values[1]
2362
2363 if (not isinstance(first_key, ast.Str) or
2364 first_key.s != 'WATCHLIST_DEFINITIONS' or
2365 not isinstance(first_value, ast.Dict)):
2366 return (
2367 'The first entry of the dict in WATCHLISTS file must be '
2368 'WATCHLIST_DEFINITIONS dict')
2369
2370 if (not isinstance(second_key, ast.Str) or
2371 second_key.s != 'WATCHLISTS' or
2372 not isinstance(second_value, ast.Dict)):
2373 return (
2374 'The second entry of the dict in WATCHLISTS file must be '
2375 'WATCHLISTS dict')
2376
2377 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132378
2379
2380def _CheckWATCHLISTS(input_api, output_api):
2381 for f in input_api.AffectedFiles(include_deletes=False):
2382 if f.LocalPath() == 'WATCHLISTS':
2383 contents = input_api.ReadFile(f, 'r')
2384
2385 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202386 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132387 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202388 # Get an AST tree for it and scan the tree for detailed style checking.
2389 expression = input_api.ast.parse(
2390 contents, filename='WATCHLISTS', mode='eval')
2391 except ValueError as e:
2392 return [output_api.PresubmitError(
2393 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2394 except SyntaxError as e:
2395 return [output_api.PresubmitError(
2396 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2397 except TypeError as e:
2398 return [output_api.PresubmitError(
2399 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132400
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202401 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2402 if result is not None:
2403 return [output_api.PresubmitError(result)]
2404 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132405
2406 return []
2407
2408
dgnaa68d5e2015-06-10 10:08:222409def _AndroidSpecificOnUploadChecks(input_api, output_api):
2410 """Groups checks that target android code."""
2411 results = []
dgnaa68d5e2015-06-10 10:08:222412 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222413 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292414 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062415 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2416 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422417 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182418 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222419 return results
2420
2421
[email protected]22c9bd72011-03-27 16:47:392422def _CommonChecks(input_api, output_api):
2423 """Checks common to both upload and commit."""
2424 results = []
2425 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382426 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542427 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582428 results.extend(
2429 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192430 results.extend(
[email protected]760deea2013-12-10 19:33:492431 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542432 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182433 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522434 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222435 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442436 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592437 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062438 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122439 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182440 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222441 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302442 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492443 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032444 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492445 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442446 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272447 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072448 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542449 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442450 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392451 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552452 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042453 results.extend(
2454 input_api.canned_checks.CheckChangeHasNoTabs(
2455 input_api,
2456 output_api,
2457 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402458 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162459 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082460 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242461 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2462 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472463 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042464 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232465 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432466 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402467 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152468 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172469 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502470 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242471 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362472 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132473 results.extend(_CheckWATCHLISTS(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242474
2475 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2476 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2477 input_api, output_api,
2478 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382479 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392480 return results
[email protected]1f7b4172010-01-28 01:17:342481
[email protected]b337cb5b2011-01-23 21:24:052482
[email protected]b8079ae4a2012-12-05 19:56:492483def _CheckPatchFiles(input_api, output_api):
2484 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2485 if f.LocalPath().endswith(('.orig', '.rej'))]
2486 if problems:
2487 return [output_api.PresubmitError(
2488 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032489 else:
2490 return []
[email protected]b8079ae4a2012-12-05 19:56:492491
2492
Kent Tamura5a8755d2017-06-29 23:37:072493def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212494 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2495 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2496 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072497 include_re = input_api.re.compile(
2498 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2499 extension_re = input_api.re.compile(r'\.[a-z]+$')
2500 errors = []
2501 for f in input_api.AffectedFiles():
2502 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2503 continue
2504 found_line_number = None
2505 found_macro = None
2506 for line_num, line in f.ChangedContents():
2507 match = macro_re.search(line)
2508 if match:
2509 found_line_number = line_num
2510 found_macro = match.group(2)
2511 break
2512 if not found_line_number:
2513 continue
2514
2515 found_include = False
2516 for line in f.NewContents():
2517 if include_re.search(line):
2518 found_include = True
2519 break
2520 if found_include:
2521 continue
2522
2523 if not f.LocalPath().endswith('.h'):
2524 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2525 try:
2526 content = input_api.ReadFile(primary_header_path, 'r')
2527 if include_re.search(content):
2528 continue
2529 except IOError:
2530 pass
2531 errors.append('%s:%d %s macro is used without including build/'
2532 'build_config.h.'
2533 % (f.LocalPath(), found_line_number, found_macro))
2534 if errors:
2535 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2536 return []
2537
2538
[email protected]b00342e7f2013-03-26 16:21:542539def _DidYouMeanOSMacro(bad_macro):
2540 try:
2541 return {'A': 'OS_ANDROID',
2542 'B': 'OS_BSD',
2543 'C': 'OS_CHROMEOS',
2544 'F': 'OS_FREEBSD',
2545 'L': 'OS_LINUX',
2546 'M': 'OS_MACOSX',
2547 'N': 'OS_NACL',
2548 'O': 'OS_OPENBSD',
2549 'P': 'OS_POSIX',
2550 'S': 'OS_SOLARIS',
2551 'W': 'OS_WIN'}[bad_macro[3].upper()]
2552 except KeyError:
2553 return ''
2554
2555
2556def _CheckForInvalidOSMacrosInFile(input_api, f):
2557 """Check for sensible looking, totally invalid OS macros."""
2558 preprocessor_statement = input_api.re.compile(r'^\s*#')
2559 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2560 results = []
2561 for lnum, line in f.ChangedContents():
2562 if preprocessor_statement.search(line):
2563 for match in os_macro.finditer(line):
2564 if not match.group(1) in _VALID_OS_MACROS:
2565 good = _DidYouMeanOSMacro(match.group(1))
2566 did_you_mean = ' (did you mean %s?)' % good if good else ''
2567 results.append(' %s:%d %s%s' % (f.LocalPath(),
2568 lnum,
2569 match.group(1),
2570 did_you_mean))
2571 return results
2572
2573
2574def _CheckForInvalidOSMacros(input_api, output_api):
2575 """Check all affected files for invalid OS macros."""
2576 bad_macros = []
2577 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472578 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542579 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2580
2581 if not bad_macros:
2582 return []
2583
2584 return [output_api.PresubmitError(
2585 'Possibly invalid OS macro[s] found. Please fix your code\n'
2586 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2587
lliabraa35bab3932014-10-01 12:16:442588
2589def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2590 """Check all affected files for invalid "if defined" macros."""
2591 ALWAYS_DEFINED_MACROS = (
2592 "TARGET_CPU_PPC",
2593 "TARGET_CPU_PPC64",
2594 "TARGET_CPU_68K",
2595 "TARGET_CPU_X86",
2596 "TARGET_CPU_ARM",
2597 "TARGET_CPU_MIPS",
2598 "TARGET_CPU_SPARC",
2599 "TARGET_CPU_ALPHA",
2600 "TARGET_IPHONE_SIMULATOR",
2601 "TARGET_OS_EMBEDDED",
2602 "TARGET_OS_IPHONE",
2603 "TARGET_OS_MAC",
2604 "TARGET_OS_UNIX",
2605 "TARGET_OS_WIN32",
2606 )
2607 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2608 results = []
2609 for lnum, line in f.ChangedContents():
2610 for match in ifdef_macro.finditer(line):
2611 if match.group(1) in ALWAYS_DEFINED_MACROS:
2612 always_defined = ' %s is always defined. ' % match.group(1)
2613 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2614 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2615 lnum,
2616 always_defined,
2617 did_you_mean))
2618 return results
2619
2620
2621def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2622 """Check all affected files for invalid "if defined" macros."""
2623 bad_macros = []
2624 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212625 if f.LocalPath().startswith('third_party/sqlite/'):
2626 continue
lliabraa35bab3932014-10-01 12:16:442627 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2628 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2629
2630 if not bad_macros:
2631 return []
2632
2633 return [output_api.PresubmitError(
2634 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2635 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2636 bad_macros)]
2637
2638
mlamouria82272622014-09-16 18:45:042639def _CheckForIPCRules(input_api, output_api):
2640 """Check for same IPC rules described in
2641 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2642 """
2643 base_pattern = r'IPC_ENUM_TRAITS\('
2644 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2645 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2646
2647 problems = []
2648 for f in input_api.AffectedSourceFiles(None):
2649 local_path = f.LocalPath()
2650 if not local_path.endswith('.h'):
2651 continue
2652 for line_number, line in f.ChangedContents():
2653 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2654 problems.append(
2655 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2656
2657 if problems:
2658 return [output_api.PresubmitPromptWarning(
2659 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2660 else:
2661 return []
2662
[email protected]b00342e7f2013-03-26 16:21:542663
mostynbb639aca52015-01-07 20:31:232664def _CheckForWindowsLineEndings(input_api, output_api):
2665 """Check source code and known ascii text files for Windows style line
2666 endings.
2667 """
earthdok1b5e0ee2015-03-10 15:19:102668 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232669
2670 file_inclusion_pattern = (
2671 known_text_files,
2672 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2673 )
2674
mostynbb639aca52015-01-07 20:31:232675 problems = []
Andrew Grieve933d12e2017-10-30 20:22:532676 source_file_filter = lambda f: input_api.FilterSourceFile(
2677 f, white_list=file_inclusion_pattern, black_list=None)
2678 for f in input_api.AffectedSourceFiles(source_file_filter):
2679 for line_number, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:232680 if line.endswith('\r\n'):
Andrew Grieve933d12e2017-10-30 20:22:532681 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:232682
2683 if problems:
2684 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2685 'these files to contain Windows style line endings?\n' +
2686 '\n'.join(problems))]
2687
2688 return []
2689
2690
pastarmovj89f7ee12016-09-20 14:58:132691def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2692 lint_filters=None, verbose_level=None):
2693 """Checks that all source files use SYSLOG properly."""
2694 syslog_files = []
2695 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562696 for line_number, line in f.ChangedContents():
2697 if 'SYSLOG' in line:
2698 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2699
pastarmovj89f7ee12016-09-20 14:58:132700 if syslog_files:
2701 return [output_api.PresubmitPromptWarning(
2702 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2703 ' calls.\nFiles to check:\n', items=syslog_files)]
2704 return []
2705
2706
[email protected]1f7b4172010-01-28 01:17:342707def CheckChangeOnUpload(input_api, output_api):
2708 results = []
2709 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472710 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282711 results.extend(
jam93a6ee792017-02-08 23:59:222712 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192713 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222714 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132715 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162716 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542717 return results
[email protected]ca8d1982009-02-19 16:33:122718
2719
[email protected]1bfb8322014-04-23 01:02:412720def GetTryServerMasterForBot(bot):
2721 """Returns the Try Server master for the given bot.
2722
[email protected]0bb112362014-07-26 04:38:322723 It tries to guess the master from the bot name, but may still fail
2724 and return None. There is no longer a default master.
2725 """
2726 # Potentially ambiguous bot names are listed explicitly.
2727 master_map = {
tandriie5587792016-07-14 00:34:502728 'chromium_presubmit': 'master.tryserver.chromium.linux',
2729 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412730 }
[email protected]0bb112362014-07-26 04:38:322731 master = master_map.get(bot)
2732 if not master:
wnwen4fbaab82016-05-25 12:54:362733 if 'android' in bot:
tandriie5587792016-07-14 00:34:502734 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362735 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502736 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322737 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502738 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322739 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502740 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322741 return master
[email protected]1bfb8322014-04-23 01:02:412742
2743
[email protected]ca8d1982009-02-19 16:33:122744def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542745 results = []
[email protected]1f7b4172010-01-28 01:17:342746 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542747 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272748 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342749 input_api,
2750 output_api,
[email protected]2fdd1f362013-01-16 03:56:032751 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272752
jam93a6ee792017-02-08 23:59:222753 results.extend(
2754 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542755 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2756 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412757 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2758 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542759 return results