blob: 02cb37a512a03d2652fc5e10fb2c93d5b47cc437 [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():
Victor Costan25079cb02017-11-04 04:55:55930 # checkperms.py file/directory arguments must be relative to the repository.
931 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11932 try:
933 input_api.subprocess.check_output(args)
934 return []
935 except input_api.subprocess.CalledProcessError as error:
936 return [output_api.PresubmitError(
937 'checkperms.py failed:',
938 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22939
940
robertocn832f5992017-01-04 19:01:30941def _CheckTeamTags(input_api, output_api):
942 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
943 checkteamtags_tool = input_api.os_path.join(
944 input_api.PresubmitLocalPath(),
945 'tools', 'checkteamtags', 'checkteamtags.py')
946 args = [input_api.python_executable, checkteamtags_tool,
947 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22948 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30949 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
950 'OWNERS']
951 try:
952 if files:
953 input_api.subprocess.check_output(args + files)
954 return []
955 except input_api.subprocess.CalledProcessError as error:
956 return [output_api.PresubmitError(
957 'checkteamtags.py failed:',
958 long_text=error.output)]
959
960
[email protected]c8278b32012-10-30 20:35:49961def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
962 """Makes sure we don't include ui/aura/window_property.h
963 in header files.
964 """
965 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
966 errors = []
967 for f in input_api.AffectedFiles():
968 if not f.LocalPath().endswith('.h'):
969 continue
970 for line_num, line in f.ChangedContents():
971 if pattern.match(line):
972 errors.append(' %s:%d' % (f.LocalPath(), line_num))
973
974 results = []
975 if errors:
976 results.append(output_api.PresubmitError(
977 'Header files should not include ui/aura/window_property.h', errors))
978 return results
979
980
[email protected]70ca77752012-11-20 03:45:03981def _CheckForVersionControlConflictsInFile(input_api, f):
982 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
983 errors = []
984 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23985 if f.LocalPath().endswith('.md'):
986 # First-level headers in markdown look a lot like version control
987 # conflict markers. http://daringfireball.net/projects/markdown/basics
988 continue
[email protected]70ca77752012-11-20 03:45:03989 if pattern.match(line):
990 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
991 return errors
992
993
994def _CheckForVersionControlConflicts(input_api, output_api):
995 """Usually this is not intentional and will cause a compile failure."""
996 errors = []
997 for f in input_api.AffectedFiles():
998 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
999
1000 results = []
1001 if errors:
1002 results.append(output_api.PresubmitError(
1003 'Version control conflict markers found, please resolve.', errors))
1004 return results
1005
estadee17314a02017-01-12 16:22:161006def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1007 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1008 errors = []
1009 for f in input_api.AffectedFiles():
1010 for line_num, line in f.ChangedContents():
1011 if pattern.search(line):
1012 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1013
1014 results = []
1015 if errors:
1016 results.append(output_api.PresubmitPromptWarning(
1017 'Found Google support URL addressed by answer number. Please replace with '
1018 'a p= identifier instead. See crbug.com/679462\n', errors))
1019 return results
1020
[email protected]70ca77752012-11-20 03:45:031021
[email protected]06e6d0ff2012-12-11 01:36:441022def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1023 def FilterFile(affected_file):
1024 """Filter function for use with input_api.AffectedSourceFiles,
1025 below. This filters out everything except non-test files from
1026 top-level directories that generally speaking should not hard-code
1027 service URLs (e.g. src/android_webview/, src/content/ and others).
1028 """
1029 return input_api.FilterSourceFile(
1030 affected_file,
[email protected]78bb39d62012-12-11 15:11:561031 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441032 black_list=(_EXCLUDED_PATHS +
1033 _TEST_CODE_EXCLUDED_PATHS +
1034 input_api.DEFAULT_BLACK_LIST))
1035
reillyi38965732015-11-16 18:27:331036 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1037 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461038 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1039 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441040 problems = [] # items are (filename, line_number, line)
1041 for f in input_api.AffectedSourceFiles(FilterFile):
1042 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461043 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441044 problems.append((f.LocalPath(), line_num, line))
1045
1046 if problems:
[email protected]f7051d52013-04-02 18:31:421047 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441048 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581049 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441050 [' %s:%d: %s' % (
1051 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031052 else:
1053 return []
[email protected]06e6d0ff2012-12-11 01:36:441054
1055
[email protected]d2530012013-01-25 16:39:271056def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1057 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311058 The native_client_sdk directory is excluded because it has auto-generated PNG
1059 files for documentation.
[email protected]d2530012013-01-25 16:39:271060 """
[email protected]d2530012013-01-25 16:39:271061 errors = []
binji0dcdf342014-12-12 18:32:311062 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1063 black_list = (r'^native_client_sdk[\\\/]',)
1064 file_filter = lambda f: input_api.FilterSourceFile(
1065 f, white_list=white_list, black_list=black_list)
1066 for f in input_api.AffectedFiles(include_deletes=False,
1067 file_filter=file_filter):
1068 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271069
1070 results = []
1071 if errors:
1072 results.append(output_api.PresubmitError(
1073 'The name of PNG files should not have abbreviations. \n'
1074 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1075 'Contact [email protected] if you have questions.', errors))
1076 return results
1077
1078
Daniel Cheng4dcdb6b2017-04-13 08:30:171079def _ExtractAddRulesFromParsedDeps(parsed_deps):
1080 """Extract the rules that add dependencies from a parsed DEPS file.
1081
1082 Args:
1083 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1084 add_rules = set()
1085 add_rules.update([
1086 rule[1:] for rule in parsed_deps.get('include_rules', [])
1087 if rule.startswith('+') or rule.startswith('!')
1088 ])
1089 for specific_file, rules in parsed_deps.get('specific_include_rules',
1090 {}).iteritems():
1091 add_rules.update([
1092 rule[1:] for rule in rules
1093 if rule.startswith('+') or rule.startswith('!')
1094 ])
1095 return add_rules
1096
1097
1098def _ParseDeps(contents):
1099 """Simple helper for parsing DEPS files."""
1100 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171101 class _VarImpl:
1102
1103 def __init__(self, local_scope):
1104 self._local_scope = local_scope
1105
1106 def Lookup(self, var_name):
1107 """Implements the Var syntax."""
1108 try:
1109 return self._local_scope['vars'][var_name]
1110 except KeyError:
1111 raise Exception('Var is not defined: %s' % var_name)
1112
1113 local_scope = {}
1114 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171115 'Var': _VarImpl(local_scope).Lookup,
1116 }
1117 exec contents in global_scope, local_scope
1118 return local_scope
1119
1120
1121def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081122 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411123 a set of DEPS entries that we should look up.
1124
1125 For a directory (rather than a specific filename) we fake a path to
1126 a specific filename by adding /DEPS. This is chosen as a file that
1127 will seldom or never be subject to per-file include_rules.
1128 """
[email protected]2b438d62013-11-14 17:54:141129 # We ignore deps entries on auto-generated directories.
1130 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081131
Daniel Cheng4dcdb6b2017-04-13 08:30:171132 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1133 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1134
1135 added_deps = new_deps.difference(old_deps)
1136
[email protected]2b438d62013-11-14 17:54:141137 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171138 for added_dep in added_deps:
1139 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1140 continue
1141 # Assume that a rule that ends in .h is a rule for a specific file.
1142 if added_dep.endswith('.h'):
1143 results.add(added_dep)
1144 else:
1145 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081146 return results
1147
1148
[email protected]e871964c2013-05-13 14:14:551149def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1150 """When a dependency prefixed with + is added to a DEPS file, we
1151 want to make sure that the change is reviewed by an OWNER of the
1152 target file or directory, to avoid layering violations from being
1153 introduced. This check verifies that this happens.
1154 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171155 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241156
1157 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191158 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241159 for f in input_api.AffectedFiles(include_deletes=False,
1160 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551161 filename = input_api.os_path.basename(f.LocalPath())
1162 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171163 virtual_depended_on_files.update(_CalculateAddedDeps(
1164 input_api.os_path,
1165 '\n'.join(f.OldContents()),
1166 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551167
[email protected]e871964c2013-05-13 14:14:551168 if not virtual_depended_on_files:
1169 return []
1170
1171 if input_api.is_committing:
1172 if input_api.tbr:
1173 return [output_api.PresubmitNotifyResult(
1174 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271175 if input_api.dry_run:
1176 return [output_api.PresubmitNotifyResult(
1177 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551178 if not input_api.change.issue:
1179 return [output_api.PresubmitError(
1180 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401181 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551182 output = output_api.PresubmitError
1183 else:
1184 output = output_api.PresubmitNotifyResult
1185
1186 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501187 owner_email, reviewers = (
1188 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1189 input_api,
1190 owners_db.email_regexp,
1191 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551192
1193 owner_email = owner_email or input_api.change.author_email
1194
[email protected]de4f7d22013-05-23 14:27:461195 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511196 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461197 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551198 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1199 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411200
1201 # We strip the /DEPS part that was added by
1202 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1203 # directory.
1204 def StripDeps(path):
1205 start_deps = path.rfind('/DEPS')
1206 if start_deps != -1:
1207 return path[:start_deps]
1208 else:
1209 return path
1210 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551211 for path in missing_files]
1212
1213 if unapproved_dependencies:
1214 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151215 output('You need LGTM from owners of depends-on paths in DEPS that were '
1216 'modified in this CL:\n %s' %
1217 '\n '.join(sorted(unapproved_dependencies)))]
1218 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1219 output_list.append(output(
1220 'Suggested missing target path OWNERS:\n %s' %
1221 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551222 return output_list
1223
1224 return []
1225
1226
[email protected]85218562013-11-22 07:41:401227def _CheckSpamLogging(input_api, output_api):
1228 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1229 black_list = (_EXCLUDED_PATHS +
1230 _TEST_CODE_EXCLUDED_PATHS +
1231 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501232 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191233 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481234 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461235 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121236 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1237 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581238 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591239 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161240 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031241 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151242 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1243 r"^chromecast[\\\/]",
1244 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481245 r"^components[\\\/]browser_watcher[\\\/]"
1246 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311247 r"^components[\\\/]html_viewer[\\\/]"
1248 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461249 # TODO(peter): Remove this exception. https://crbug.com/534537
1250 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1251 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251252 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1253 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241254 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111255 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151256 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111257 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521258 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501259 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361260 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311261 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131262 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001263 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441264 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451265 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021266 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351267 r"dump_file_system.cc$",
1268 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401269 source_file_filter = lambda x: input_api.FilterSourceFile(
1270 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1271
thomasanderson625d3932017-03-29 07:16:581272 log_info = set([])
1273 printf = set([])
[email protected]85218562013-11-22 07:41:401274
1275 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581276 for _, line in f.ChangedContents():
1277 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1278 log_info.add(f.LocalPath())
1279 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1280 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371281
thomasanderson625d3932017-03-29 07:16:581282 if input_api.re.search(r"\bprintf\(", line):
1283 printf.add(f.LocalPath())
1284 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1285 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401286
1287 if log_info:
1288 return [output_api.PresubmitError(
1289 'These files spam the console log with LOG(INFO):',
1290 items=log_info)]
1291 if printf:
1292 return [output_api.PresubmitError(
1293 'These files spam the console log with printf/fprintf:',
1294 items=printf)]
1295 return []
1296
1297
[email protected]49aa76a2013-12-04 06:59:161298def _CheckForAnonymousVariables(input_api, output_api):
1299 """These types are all expected to hold locks while in scope and
1300 so should never be anonymous (which causes them to be immediately
1301 destroyed)."""
1302 they_who_must_be_named = [
1303 'base::AutoLock',
1304 'base::AutoReset',
1305 'base::AutoUnlock',
1306 'SkAutoAlphaRestore',
1307 'SkAutoBitmapShaderInstall',
1308 'SkAutoBlitterChoose',
1309 'SkAutoBounderCommit',
1310 'SkAutoCallProc',
1311 'SkAutoCanvasRestore',
1312 'SkAutoCommentBlock',
1313 'SkAutoDescriptor',
1314 'SkAutoDisableDirectionCheck',
1315 'SkAutoDisableOvalCheck',
1316 'SkAutoFree',
1317 'SkAutoGlyphCache',
1318 'SkAutoHDC',
1319 'SkAutoLockColors',
1320 'SkAutoLockPixels',
1321 'SkAutoMalloc',
1322 'SkAutoMaskFreeImage',
1323 'SkAutoMutexAcquire',
1324 'SkAutoPathBoundsUpdate',
1325 'SkAutoPDFRelease',
1326 'SkAutoRasterClipValidate',
1327 'SkAutoRef',
1328 'SkAutoTime',
1329 'SkAutoTrace',
1330 'SkAutoUnref',
1331 ]
1332 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1333 # bad: base::AutoLock(lock.get());
1334 # not bad: base::AutoLock lock(lock.get());
1335 bad_pattern = input_api.re.compile(anonymous)
1336 # good: new base::AutoLock(lock.get())
1337 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1338 errors = []
1339
1340 for f in input_api.AffectedFiles():
1341 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1342 continue
1343 for linenum, line in f.ChangedContents():
1344 if bad_pattern.search(line) and not good_pattern.search(line):
1345 errors.append('%s:%d' % (f.LocalPath(), linenum))
1346
1347 if errors:
1348 return [output_api.PresubmitError(
1349 'These lines create anonymous variables that need to be named:',
1350 items=errors)]
1351 return []
1352
1353
[email protected]999261d2014-03-03 20:08:081354def _CheckUserActionUpdate(input_api, output_api):
1355 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521356 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081357 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521358 # If actions.xml is already included in the changelist, the PRESUBMIT
1359 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081360 return []
1361
[email protected]999261d2014-03-03 20:08:081362 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1363 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521364 current_actions = None
[email protected]999261d2014-03-03 20:08:081365 for f in input_api.AffectedFiles(file_filter=file_filter):
1366 for line_num, line in f.ChangedContents():
1367 match = input_api.re.search(action_re, line)
1368 if match:
[email protected]2f92dec2014-03-07 19:21:521369 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1370 # loaded only once.
1371 if not current_actions:
1372 with open('tools/metrics/actions/actions.xml') as actions_f:
1373 current_actions = actions_f.read()
1374 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081375 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521376 action = 'name="{0}"'.format(action_name)
1377 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081378 return [output_api.PresubmitPromptWarning(
1379 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521380 'tools/metrics/actions/actions.xml. Please run '
1381 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081382 % (f.LocalPath(), line_num, action_name))]
1383 return []
1384
1385
Daniel Cheng13ca61a882017-08-25 15:11:251386def _ImportJSONCommentEater(input_api):
1387 import sys
1388 sys.path = sys.path + [input_api.os_path.join(
1389 input_api.PresubmitLocalPath(),
1390 'tools', 'json_comment_eater')]
1391 import json_comment_eater
1392 return json_comment_eater
1393
1394
[email protected]99171a92014-06-03 08:44:471395def _GetJSONParseError(input_api, filename, eat_comments=True):
1396 try:
1397 contents = input_api.ReadFile(filename)
1398 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251399 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131400 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471401
1402 input_api.json.loads(contents)
1403 except ValueError as e:
1404 return e
1405 return None
1406
1407
1408def _GetIDLParseError(input_api, filename):
1409 try:
1410 contents = input_api.ReadFile(filename)
1411 idl_schema = input_api.os_path.join(
1412 input_api.PresubmitLocalPath(),
1413 'tools', 'json_schema_compiler', 'idl_schema.py')
1414 process = input_api.subprocess.Popen(
1415 [input_api.python_executable, idl_schema],
1416 stdin=input_api.subprocess.PIPE,
1417 stdout=input_api.subprocess.PIPE,
1418 stderr=input_api.subprocess.PIPE,
1419 universal_newlines=True)
1420 (_, error) = process.communicate(input=contents)
1421 return error or None
1422 except ValueError as e:
1423 return e
1424
1425
1426def _CheckParseErrors(input_api, output_api):
1427 """Check that IDL and JSON files do not contain syntax errors."""
1428 actions = {
1429 '.idl': _GetIDLParseError,
1430 '.json': _GetJSONParseError,
1431 }
[email protected]99171a92014-06-03 08:44:471432 # Most JSON files are preprocessed and support comments, but these do not.
1433 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491434 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471435 ]
1436 # Only run IDL checker on files in these directories.
1437 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491438 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1439 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471440 ]
1441
1442 def get_action(affected_file):
1443 filename = affected_file.LocalPath()
1444 return actions.get(input_api.os_path.splitext(filename)[1])
1445
[email protected]99171a92014-06-03 08:44:471446 def FilterFile(affected_file):
1447 action = get_action(affected_file)
1448 if not action:
1449 return False
1450 path = affected_file.LocalPath()
1451
Sean Kau46e29bc2017-08-28 16:31:161452 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471453 return False
1454
1455 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161456 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471457 return False
1458 return True
1459
1460 results = []
1461 for affected_file in input_api.AffectedFiles(
1462 file_filter=FilterFile, include_deletes=False):
1463 action = get_action(affected_file)
1464 kwargs = {}
1465 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161466 _MatchesFile(input_api, json_no_comments_patterns,
1467 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471468 kwargs['eat_comments'] = False
1469 parse_error = action(input_api,
1470 affected_file.AbsoluteLocalPath(),
1471 **kwargs)
1472 if parse_error:
1473 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1474 (affected_file.LocalPath(), parse_error)))
1475 return results
1476
1477
[email protected]760deea2013-12-10 19:33:491478def _CheckJavaStyle(input_api, output_api):
1479 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471480 import sys
[email protected]760deea2013-12-10 19:33:491481 original_sys_path = sys.path
1482 try:
1483 sys.path = sys.path + [input_api.os_path.join(
1484 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1485 import checkstyle
1486 finally:
1487 # Restore sys.path to what it was before.
1488 sys.path = original_sys_path
1489
1490 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091491 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511492 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491493
1494
Sean Kau46e29bc2017-08-28 16:31:161495def _MatchesFile(input_api, patterns, path):
1496 for pattern in patterns:
1497 if input_api.re.search(pattern, path):
1498 return True
1499 return False
1500
1501
dchenge07de812016-06-20 19:27:171502def _CheckIpcOwners(input_api, output_api):
1503 """Checks that affected files involving IPC have an IPC OWNERS rule.
1504
1505 Whether or not a file affects IPC is determined by a simple whitelist of
1506 filename patterns."""
1507 file_patterns = [
palmerb19a0932017-01-24 04:00:311508 # Legacy IPC:
dchenge07de812016-06-20 19:27:171509 '*_messages.cc',
1510 '*_messages*.h',
1511 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311512 # Mojo IPC:
dchenge07de812016-06-20 19:27:171513 '*.mojom',
1514 '*_struct_traits*.*',
1515 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311516 '*.typemap',
1517 # Android native IPC:
1518 '*.aidl',
1519 # Blink uses a different file naming convention:
1520 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171521 '*StructTraits*.*',
1522 '*TypeConverter*.*',
1523 ]
1524
scottmg7a6ed5ba2016-11-04 18:22:041525 # These third_party directories do not contain IPCs, but contain files
1526 # matching the above patterns, which trigger false positives.
1527 exclude_paths = [
1528 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291529 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041530 ]
1531
dchenge07de812016-06-20 19:27:171532 # Dictionary mapping an OWNERS file path to Patterns.
1533 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1534 # rules ) to a PatternEntry.
1535 # PatternEntry is a dictionary with two keys:
1536 # - 'files': the files that are matched by this pattern
1537 # - 'rules': the per-file rules needed for this pattern
1538 # For example, if we expect OWNERS file to contain rules for *.mojom and
1539 # *_struct_traits*.*, Patterns might look like this:
1540 # {
1541 # '*.mojom': {
1542 # 'files': ...,
1543 # 'rules': [
1544 # 'per-file *.mojom=set noparent',
1545 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1546 # ],
1547 # },
1548 # '*_struct_traits*.*': {
1549 # 'files': ...,
1550 # 'rules': [
1551 # 'per-file *_struct_traits*.*=set noparent',
1552 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1553 # ],
1554 # },
1555 # }
1556 to_check = {}
1557
Daniel Cheng13ca61a882017-08-25 15:11:251558 def AddPatternToCheck(input_file, pattern):
1559 owners_file = input_api.os_path.join(
1560 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1561 if owners_file not in to_check:
1562 to_check[owners_file] = {}
1563 if pattern not in to_check[owners_file]:
1564 to_check[owners_file][pattern] = {
1565 'files': [],
1566 'rules': [
1567 'per-file %s=set noparent' % pattern,
1568 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1569 ]
1570 }
1571 to_check[owners_file][pattern]['files'].append(f)
1572
dchenge07de812016-06-20 19:27:171573 # Iterate through the affected files to see what we actually need to check
1574 # for. We should only nag patch authors about per-file rules if a file in that
1575 # directory would match that pattern. If a directory only contains *.mojom
1576 # files and no *_messages*.h files, we should only nag about rules for
1577 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251578 for f in input_api.AffectedFiles(include_deletes=False):
1579 # Manifest files don't have a strong naming convention. Instead, scan
1580 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161581 if (f.LocalPath().endswith('.json') and
1582 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1583 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251584 json_comment_eater = _ImportJSONCommentEater(input_api)
1585 mostly_json_lines = '\n'.join(f.NewContents())
1586 # Comments aren't allowed in strict JSON, so filter them out.
1587 json_lines = json_comment_eater.Nom(mostly_json_lines)
1588 json_content = input_api.json.loads(json_lines)
1589 if 'interface_provider_specs' in json_content:
1590 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171591 for pattern in file_patterns:
1592 if input_api.fnmatch.fnmatch(
1593 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041594 skip = False
1595 for exclude in exclude_paths:
1596 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1597 skip = True
1598 break
1599 if skip:
1600 continue
Daniel Cheng13ca61a882017-08-25 15:11:251601 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171602 break
1603
1604 # Now go through the OWNERS files we collected, filtering out rules that are
1605 # already present in that OWNERS file.
1606 for owners_file, patterns in to_check.iteritems():
1607 try:
1608 with file(owners_file) as f:
1609 lines = set(f.read().splitlines())
1610 for entry in patterns.itervalues():
1611 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1612 ]
1613 except IOError:
1614 # No OWNERS file, so all the rules are definitely missing.
1615 continue
1616
1617 # All the remaining lines weren't found in OWNERS files, so emit an error.
1618 errors = []
1619 for owners_file, patterns in to_check.iteritems():
1620 missing_lines = []
1621 files = []
1622 for pattern, entry in patterns.iteritems():
1623 missing_lines.extend(entry['rules'])
1624 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1625 if missing_lines:
1626 errors.append(
Daniel Cheng52111692017-06-14 08:00:591627 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171628 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1629
1630 results = []
1631 if errors:
vabrf5ce3bf92016-07-11 14:52:411632 if input_api.is_committing:
1633 output = output_api.PresubmitError
1634 else:
1635 output = output_api.PresubmitPromptWarning
1636 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591637 'Found OWNERS files that need to be updated for IPC security ' +
1638 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171639 long_text='\n\n'.join(errors)))
1640
1641 return results
1642
1643
jbriance9e12f162016-11-25 07:57:501644def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311645 """Checks that added or removed lines in non third party affected
1646 header files do not lead to new useless class or struct forward
1647 declaration.
jbriance9e12f162016-11-25 07:57:501648 """
1649 results = []
1650 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1651 input_api.re.MULTILINE)
1652 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1653 input_api.re.MULTILINE)
1654 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311655 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191656 not f.LocalPath().startswith('third_party/blink') and
1657 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311658 not f.LocalPath().startswith('third_party/WebKit') and
1659 not f.LocalPath().startswith('third_party\\WebKit')):
1660 continue
1661
jbriance9e12f162016-11-25 07:57:501662 if not f.LocalPath().endswith('.h'):
1663 continue
1664
1665 contents = input_api.ReadFile(f)
1666 fwd_decls = input_api.re.findall(class_pattern, contents)
1667 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1668
1669 useless_fwd_decls = []
1670 for decl in fwd_decls:
1671 count = sum(1 for _ in input_api.re.finditer(
1672 r'\b%s\b' % input_api.re.escape(decl), contents))
1673 if count == 1:
1674 useless_fwd_decls.append(decl)
1675
1676 if not useless_fwd_decls:
1677 continue
1678
1679 for line in f.GenerateScmDiff().splitlines():
1680 if (line.startswith('-') and not line.startswith('--') or
1681 line.startswith('+') and not line.startswith('++')):
1682 for decl in useless_fwd_decls:
1683 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1684 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241685 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501686 (f.LocalPath(), decl)))
1687 useless_fwd_decls.remove(decl)
1688
1689 return results
1690
1691
dskiba88634f4e2015-08-14 23:03:291692def _CheckAndroidToastUsage(input_api, output_api):
1693 """Checks that code uses org.chromium.ui.widget.Toast instead of
1694 android.widget.Toast (Chromium Toast doesn't force hardware
1695 acceleration on low-end devices, saving memory).
1696 """
1697 toast_import_pattern = input_api.re.compile(
1698 r'^import android\.widget\.Toast;$')
1699
1700 errors = []
1701
1702 sources = lambda affected_file: input_api.FilterSourceFile(
1703 affected_file,
1704 black_list=(_EXCLUDED_PATHS +
1705 _TEST_CODE_EXCLUDED_PATHS +
1706 input_api.DEFAULT_BLACK_LIST +
1707 (r'^chromecast[\\\/].*',
1708 r'^remoting[\\\/].*')),
1709 white_list=(r'.*\.java$',))
1710
1711 for f in input_api.AffectedSourceFiles(sources):
1712 for line_num, line in f.ChangedContents():
1713 if toast_import_pattern.search(line):
1714 errors.append("%s:%d" % (f.LocalPath(), line_num))
1715
1716 results = []
1717
1718 if errors:
1719 results.append(output_api.PresubmitError(
1720 'android.widget.Toast usage is detected. Android toasts use hardware'
1721 ' acceleration, and can be\ncostly on low-end devices. Please use'
1722 ' org.chromium.ui.widget.Toast instead.\n'
1723 'Contact [email protected] if you have any questions.',
1724 errors))
1725
1726 return results
1727
1728
dgnaa68d5e2015-06-10 10:08:221729def _CheckAndroidCrLogUsage(input_api, output_api):
1730 """Checks that new logs using org.chromium.base.Log:
1731 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511732 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221733 """
pkotwicza1dd0b002016-05-16 14:41:041734
torne89540622017-03-24 19:41:301735 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041736 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301737 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041738 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301739 # WebView license viewer code cannot depend on //base; used in stub APK.
1740 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1741 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041742 ]
1743
dgnaa68d5e2015-06-10 10:08:221744 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121745 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1746 class_in_base_pattern = input_api.re.compile(
1747 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1748 has_some_log_import_pattern = input_api.re.compile(
1749 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221750 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121751 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221752 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511753 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221754 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221755
Vincent Scheib16d7b272015-09-15 18:09:071756 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221757 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041758 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1759 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121760
dgnaa68d5e2015-06-10 10:08:221761 tag_decl_errors = []
1762 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121763 tag_errors = []
dgn38736db2015-09-18 19:20:511764 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121765 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221766
1767 for f in input_api.AffectedSourceFiles(sources):
1768 file_content = input_api.ReadFile(f)
1769 has_modified_logs = False
1770
1771 # Per line checks
dgn87d9fb62015-06-12 09:15:121772 if (cr_log_import_pattern.search(file_content) or
1773 (class_in_base_pattern.search(file_content) and
1774 not has_some_log_import_pattern.search(file_content))):
1775 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221776 for line_num, line in f.ChangedContents():
1777
1778 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121779 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221780 if match:
1781 has_modified_logs = True
1782
1783 # Make sure it uses "TAG"
1784 if not match.group('tag') == 'TAG':
1785 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121786 else:
1787 # Report non cr Log function calls in changed lines
1788 for line_num, line in f.ChangedContents():
1789 if log_call_pattern.search(line):
1790 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221791
1792 # Per file checks
1793 if has_modified_logs:
1794 # Make sure the tag is using the "cr" prefix and is not too long
1795 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511796 tag_name = match.group('name') if match else None
1797 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221798 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511799 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221800 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511801 elif '.' in tag_name:
1802 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221803
1804 results = []
1805 if tag_decl_errors:
1806 results.append(output_api.PresubmitPromptWarning(
1807 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511808 '"private static final String TAG = "<package tag>".\n'
1809 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221810 tag_decl_errors))
1811
1812 if tag_length_errors:
1813 results.append(output_api.PresubmitError(
1814 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511815 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221816 tag_length_errors))
1817
1818 if tag_errors:
1819 results.append(output_api.PresubmitPromptWarning(
1820 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1821 tag_errors))
1822
dgn87d9fb62015-06-12 09:15:121823 if util_log_errors:
dgn4401aa52015-04-29 16:26:171824 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121825 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1826 util_log_errors))
1827
dgn38736db2015-09-18 19:20:511828 if tag_with_dot_errors:
1829 results.append(output_api.PresubmitPromptWarning(
1830 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1831 tag_with_dot_errors))
1832
dgn4401aa52015-04-29 16:26:171833 return results
1834
1835
Yoland Yanb92fa522017-08-28 17:37:061836def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1837 """Checks that junit.framework.* is no longer used."""
1838 deprecated_junit_framework_pattern = input_api.re.compile(
1839 r'^import junit\.framework\..*;',
1840 input_api.re.MULTILINE)
1841 sources = lambda x: input_api.FilterSourceFile(
1842 x, white_list=(r'.*\.java$',), black_list=None)
1843 errors = []
1844 for f in input_api.AffectedFiles(sources):
1845 for line_num, line in f.ChangedContents():
1846 if deprecated_junit_framework_pattern.search(line):
1847 errors.append("%s:%d" % (f.LocalPath(), line_num))
1848
1849 results = []
1850 if errors:
1851 results.append(output_api.PresubmitError(
1852 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1853 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1854 ' if you have any question.', errors))
1855 return results
1856
1857
1858def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1859 """Checks that if new Java test classes have inheritance.
1860 Either the new test class is JUnit3 test or it is a JUnit4 test class
1861 with a base class, either case is undesirable.
1862 """
1863 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1864
1865 sources = lambda x: input_api.FilterSourceFile(
1866 x, white_list=(r'.*Test\.java$',), black_list=None)
1867 errors = []
1868 for f in input_api.AffectedFiles(sources):
1869 if not f.OldContents():
1870 class_declaration_start_flag = False
1871 for line_num, line in f.ChangedContents():
1872 if class_declaration_pattern.search(line):
1873 class_declaration_start_flag = True
1874 if class_declaration_start_flag and ' extends ' in line:
1875 errors.append('%s:%d' % (f.LocalPath(), line_num))
1876 if '{' in line:
1877 class_declaration_start_flag = False
1878
1879 results = []
1880 if errors:
1881 results.append(output_api.PresubmitPromptWarning(
1882 'The newly created files include Test classes that inherits from base'
1883 ' class. Please do not use inheritance in JUnit4 tests or add new'
1884 ' JUnit3 tests. Contact [email protected] if you have any'
1885 ' questions.', errors))
1886 return results
1887
yolandyan45001472016-12-21 21:12:421888def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1889 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1890 deprecated_annotation_import_pattern = input_api.re.compile(
1891 r'^import android\.test\.suitebuilder\.annotation\..*;',
1892 input_api.re.MULTILINE)
1893 sources = lambda x: input_api.FilterSourceFile(
1894 x, white_list=(r'.*\.java$',), black_list=None)
1895 errors = []
1896 for f in input_api.AffectedFiles(sources):
1897 for line_num, line in f.ChangedContents():
1898 if deprecated_annotation_import_pattern.search(line):
1899 errors.append("%s:%d" % (f.LocalPath(), line_num))
1900
1901 results = []
1902 if errors:
1903 results.append(output_api.PresubmitError(
1904 'Annotations in android.test.suitebuilder.annotation have been'
1905 ' deprecated since API level 24. Please use android.support.test.filters'
1906 ' from //third_party/android_support_test_runner:runner_java instead.'
1907 ' Contact [email protected] if you have any questions.', errors))
1908 return results
1909
1910
agrieve7b6479d82015-10-07 14:24:221911def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1912 """Checks if MDPI assets are placed in a correct directory."""
1913 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1914 ('/res/drawable/' in f.LocalPath() or
1915 '/res/drawable-ldrtl/' in f.LocalPath()))
1916 errors = []
1917 for f in input_api.AffectedFiles(include_deletes=False,
1918 file_filter=file_filter):
1919 errors.append(' %s' % f.LocalPath())
1920
1921 results = []
1922 if errors:
1923 results.append(output_api.PresubmitError(
1924 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1925 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1926 '/res/drawable-ldrtl/.\n'
1927 'Contact [email protected] if you have questions.', errors))
1928 return results
1929
1930
Nate Fischer535972b2017-09-16 01:06:181931def _CheckAndroidWebkitImports(input_api, output_api):
1932 """Checks that code uses org.chromium.base.Callback instead of
1933 android.widget.ValueCallback except in the WebView glue layer.
1934 """
1935 valuecallback_import_pattern = input_api.re.compile(
1936 r'^import android\.webkit\.ValueCallback;$')
1937
1938 errors = []
1939
1940 sources = lambda affected_file: input_api.FilterSourceFile(
1941 affected_file,
1942 black_list=(_EXCLUDED_PATHS +
1943 _TEST_CODE_EXCLUDED_PATHS +
1944 input_api.DEFAULT_BLACK_LIST +
1945 (r'^android_webview[\\\/]glue[\\\/].*',)),
1946 white_list=(r'.*\.java$',))
1947
1948 for f in input_api.AffectedSourceFiles(sources):
1949 for line_num, line in f.ChangedContents():
1950 if valuecallback_import_pattern.search(line):
1951 errors.append("%s:%d" % (f.LocalPath(), line_num))
1952
1953 results = []
1954
1955 if errors:
1956 results.append(output_api.PresubmitError(
1957 'android.webkit.ValueCallback usage is detected outside of the glue'
1958 ' layer. To stay compatible with the support library, android.webkit.*'
1959 ' classes should only be used inside the glue layer and'
1960 ' org.chromium.base.Callback should be used instead.',
1961 errors))
1962
1963 return results
1964
1965
agrievef32bcc72016-04-04 14:57:401966class PydepsChecker(object):
1967 def __init__(self, input_api, pydeps_files):
1968 self._file_cache = {}
1969 self._input_api = input_api
1970 self._pydeps_files = pydeps_files
1971
1972 def _LoadFile(self, path):
1973 """Returns the list of paths within a .pydeps file relative to //."""
1974 if path not in self._file_cache:
1975 with open(path) as f:
1976 self._file_cache[path] = f.read()
1977 return self._file_cache[path]
1978
1979 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1980 """Returns an interable of paths within the .pydep, relativized to //."""
1981 os_path = self._input_api.os_path
1982 pydeps_dir = os_path.dirname(pydeps_path)
1983 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1984 if not l.startswith('*'))
1985 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1986
1987 def _CreateFilesToPydepsMap(self):
1988 """Returns a map of local_path -> list_of_pydeps."""
1989 ret = {}
1990 for pydep_local_path in self._pydeps_files:
1991 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1992 ret.setdefault(path, []).append(pydep_local_path)
1993 return ret
1994
1995 def ComputeAffectedPydeps(self):
1996 """Returns an iterable of .pydeps files that might need regenerating."""
1997 affected_pydeps = set()
1998 file_to_pydeps_map = None
1999 for f in self._input_api.AffectedFiles(include_deletes=True):
2000 local_path = f.LocalPath()
2001 if local_path == 'DEPS':
2002 return self._pydeps_files
2003 elif local_path.endswith('.pydeps'):
2004 if local_path in self._pydeps_files:
2005 affected_pydeps.add(local_path)
2006 elif local_path.endswith('.py'):
2007 if file_to_pydeps_map is None:
2008 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2009 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2010 return affected_pydeps
2011
2012 def DetermineIfStale(self, pydeps_path):
2013 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412014 import difflib
agrievef32bcc72016-04-04 14:57:402015 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2016 cmd = old_pydeps_data[1][1:].strip()
John Budorickab2fa102017-10-06 16:59:492017 env = {
2018 'PYTHONDONTWRITEBYTECODE': '1'
2019 }
agrievef32bcc72016-04-04 14:57:402020 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorickab2fa102017-10-06 16:59:492021 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412022 old_contents = old_pydeps_data[2:]
2023 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402024 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412025 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402026
2027
2028def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2029 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:002030 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:282031 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
2032 # Mac, so skip it on other platforms.
2033 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002034 return []
agrievef32bcc72016-04-04 14:57:402035 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
2036 is_android = input_api.os_path.exists('third_party/android_tools')
2037 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2038 results = []
2039 # First, check for new / deleted .pydeps.
2040 for f in input_api.AffectedFiles(include_deletes=True):
2041 if f.LocalPath().endswith('.pydeps'):
2042 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2043 results.append(output_api.PresubmitError(
2044 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2045 'remove %s' % f.LocalPath()))
2046 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2047 results.append(output_api.PresubmitError(
2048 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2049 'include %s' % f.LocalPath()))
2050
2051 if results:
2052 return results
2053
2054 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2055
2056 for pydep_path in checker.ComputeAffectedPydeps():
2057 try:
phajdan.jr0d9878552016-11-04 10:49:412058 result = checker.DetermineIfStale(pydep_path)
2059 if result:
2060 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402061 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412062 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2063 'To regenerate, run:\n\n %s' %
2064 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402065 except input_api.subprocess.CalledProcessError as error:
2066 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2067 long_text=error.output)]
2068
2069 return results
2070
2071
glidere61efad2015-02-18 17:39:432072def _CheckSingletonInHeaders(input_api, output_api):
2073 """Checks to make sure no header files have |Singleton<|."""
2074 def FileFilter(affected_file):
2075 # It's ok for base/memory/singleton.h to have |Singleton<|.
2076 black_list = (_EXCLUDED_PATHS +
2077 input_api.DEFAULT_BLACK_LIST +
2078 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2079 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2080
sergeyu34d21222015-09-16 00:11:442081 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432082 files = []
2083 for f in input_api.AffectedSourceFiles(FileFilter):
2084 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2085 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2086 contents = input_api.ReadFile(f)
2087 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242088 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432089 pattern.search(line)):
2090 files.append(f)
2091 break
2092
2093 if files:
yolandyandaabc6d2016-04-18 18:29:392094 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442095 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432096 'Please move them to an appropriate source file so that the ' +
2097 'template gets instantiated in a single compilation unit.',
2098 files) ]
2099 return []
2100
2101
[email protected]fd20b902014-05-09 02:14:532102_DEPRECATED_CSS = [
2103 # Values
2104 ( "-webkit-box", "flex" ),
2105 ( "-webkit-inline-box", "inline-flex" ),
2106 ( "-webkit-flex", "flex" ),
2107 ( "-webkit-inline-flex", "inline-flex" ),
2108 ( "-webkit-min-content", "min-content" ),
2109 ( "-webkit-max-content", "max-content" ),
2110
2111 # Properties
2112 ( "-webkit-background-clip", "background-clip" ),
2113 ( "-webkit-background-origin", "background-origin" ),
2114 ( "-webkit-background-size", "background-size" ),
2115 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442116 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532117
2118 # Functions
2119 ( "-webkit-gradient", "gradient" ),
2120 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2121 ( "-webkit-linear-gradient", "linear-gradient" ),
2122 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2123 ( "-webkit-radial-gradient", "radial-gradient" ),
2124 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2125]
2126
dbeam1ec68ac2016-12-15 05:22:242127def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532128 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252129 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342130 documentation and iOS CSS for dom distiller
2131 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252132 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532133 results = []
dbeam070cfe62014-10-22 06:44:022134 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252135 black_list = (_EXCLUDED_PATHS +
2136 _TEST_CODE_EXCLUDED_PATHS +
2137 input_api.DEFAULT_BLACK_LIST +
2138 (r"^chrome/common/extensions/docs",
2139 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342140 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442141 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252142 r"^native_client_sdk"))
2143 file_filter = lambda f: input_api.FilterSourceFile(
2144 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532145 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2146 for line_num, line in fpath.ChangedContents():
2147 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022148 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532149 results.append(output_api.PresubmitError(
2150 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2151 (fpath.LocalPath(), line_num, deprecated_value, value)))
2152 return results
2153
mohan.reddyf21db962014-10-16 12:26:472154
dbeam070cfe62014-10-22 06:44:022155_DEPRECATED_JS = [
2156 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2157 ( "__defineGetter__", "Object.defineProperty" ),
2158 ( "__defineSetter__", "Object.defineProperty" ),
2159]
2160
dbeam1ec68ac2016-12-15 05:22:242161def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022162 """Make sure that we don't use deprecated JS in Chrome code."""
2163 results = []
2164 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2165 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2166 input_api.DEFAULT_BLACK_LIST)
2167 file_filter = lambda f: input_api.FilterSourceFile(
2168 f, white_list=file_inclusion_pattern, black_list=black_list)
2169 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2170 for lnum, line in fpath.ChangedContents():
2171 for (deprecated, replacement) in _DEPRECATED_JS:
2172 if deprecated in line:
2173 results.append(output_api.PresubmitError(
2174 "%s:%d: Use of deprecated JS %s, use %s instead" %
2175 (fpath.LocalPath(), lnum, deprecated, replacement)))
2176 return results
2177
dpapadd651231d82017-07-21 02:44:472178def _CheckForRiskyJsArrowFunction(line_number, line):
2179 if ' => ' in line:
2180 return "line %d, is using an => (arrow) function\n %s\n" % (
2181 line_number, line)
2182 return ''
2183
2184def _CheckForRiskyJsConstLet(input_api, line_number, line):
2185 if input_api.re.match('^\s*(const|let)\s', line):
2186 return "line %d, is using const/let keyword\n %s\n" % (
2187 line_number, line)
2188 return ''
dbeam070cfe62014-10-22 06:44:022189
dbeam1ec68ac2016-12-15 05:22:242190def _CheckForRiskyJsFeatures(input_api, output_api):
2191 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002192 # 'ui/webui/resources/cr_components are not allowed on ios'
2193 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572194 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002195 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472196 results = []
dbeam1ec68ac2016-12-15 05:22:242197 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472198 arrow_error_lines = []
2199 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242200 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472201 arrow_error_lines += filter(None, [
2202 _CheckForRiskyJsArrowFunction(lnum, line),
2203 ])
dbeam1ec68ac2016-12-15 05:22:242204
dpapadd651231d82017-07-21 02:44:472205 const_let_error_lines += filter(None, [
2206 _CheckForRiskyJsConstLet(input_api, lnum, line),
2207 ])
dbeam1ec68ac2016-12-15 05:22:242208
dpapadd651231d82017-07-21 02:44:472209 if arrow_error_lines:
2210 arrow_error_lines = map(
2211 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2212 results.append(
2213 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2214"""
2215Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242216%s
2217Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2218https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472219""" % f.LocalPath()
2220 ])))
dbeam1ec68ac2016-12-15 05:22:242221
dpapadd651231d82017-07-21 02:44:472222 if const_let_error_lines:
2223 const_let_error_lines = map(
2224 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2225 results.append(
2226 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2227"""
2228Use of const/let keywords detected in:
2229%s
2230Please ensure your code does not run on iOS9 because const/let is not fully
2231supported.
2232https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2233https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2234""" % f.LocalPath()
2235 ])))
2236
2237 return results
dbeam1ec68ac2016-12-15 05:22:242238
rlanday6802cf632017-05-30 17:48:362239def _CheckForRelativeIncludes(input_api, output_api):
2240 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2241 import sys
2242 original_sys_path = sys.path
2243 try:
2244 sys.path = sys.path + [input_api.os_path.join(
2245 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2246 from cpp_checker import CppChecker
2247 finally:
2248 # Restore sys.path to what it was before.
2249 sys.path = original_sys_path
2250
2251 bad_files = {}
2252 for f in input_api.AffectedFiles(include_deletes=False):
2253 if (f.LocalPath().startswith('third_party') and
2254 not f.LocalPath().startswith('third_party/WebKit') and
2255 not f.LocalPath().startswith('third_party\\WebKit')):
2256 continue
2257
2258 if not CppChecker.IsCppFile(f.LocalPath()):
2259 continue
2260
2261 relative_includes = [line for line_num, line in f.ChangedContents()
2262 if "#include" in line and "../" in line]
2263 if not relative_includes:
2264 continue
2265 bad_files[f.LocalPath()] = relative_includes
2266
2267 if not bad_files:
2268 return []
2269
2270 error_descriptions = []
2271 for file_path, bad_lines in bad_files.iteritems():
2272 error_description = file_path
2273 for line in bad_lines:
2274 error_description += '\n ' + line
2275 error_descriptions.append(error_description)
2276
2277 results = []
2278 results.append(output_api.PresubmitError(
2279 'You added one or more relative #include paths (including "../").\n'
2280 'These shouldn\'t be used because they can be used to include headers\n'
2281 'from code that\'s not correctly specified as a dependency in the\n'
2282 'relevant BUILD.gn file(s).',
2283 error_descriptions))
2284
2285 return results
2286
Takeshi Yoshinoe387aa32017-08-02 13:16:132287
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202288def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2289 if not isinstance(key, ast.Str):
2290 return 'Key at line %d must be a string literal' % key.lineno
2291 if not isinstance(value, ast.Dict):
2292 return 'Value at line %d must be a dict' % value.lineno
2293 if len(value.keys) != 1:
2294 return 'Dict at line %d must have single entry' % value.lineno
2295 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2296 return (
2297 'Entry at line %d must have a string literal \'filepath\' as key' %
2298 value.lineno)
2299 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132300
Takeshi Yoshinoe387aa32017-08-02 13:16:132301
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202302def _CheckWatchlistsEntrySyntax(key, value, ast):
2303 if not isinstance(key, ast.Str):
2304 return 'Key at line %d must be a string literal' % key.lineno
2305 if not isinstance(value, ast.List):
2306 return 'Value at line %d must be a list' % value.lineno
2307 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132308
Takeshi Yoshinoe387aa32017-08-02 13:16:132309
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202310def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2311 mismatch_template = (
2312 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2313 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132314
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202315 i = 0
2316 last_key = ''
2317 while True:
2318 if i >= len(wd_dict.keys):
2319 if i >= len(w_dict.keys):
2320 return None
2321 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2322 elif i >= len(w_dict.keys):
2323 return (
2324 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132325
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202326 wd_key = wd_dict.keys[i]
2327 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132328
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202329 result = _CheckWatchlistDefinitionsEntrySyntax(
2330 wd_key, wd_dict.values[i], ast)
2331 if result is not None:
2332 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132333
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202334 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2335 if result is not None:
2336 return 'Bad entry in WATCHLISTS dict: %s' % result
2337
2338 if wd_key.s != w_key.s:
2339 return mismatch_template % (
2340 '%s at line %d' % (wd_key.s, wd_key.lineno),
2341 '%s at line %d' % (w_key.s, w_key.lineno))
2342
2343 if wd_key.s < last_key:
2344 return (
2345 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2346 (wd_key.lineno, w_key.lineno))
2347 last_key = wd_key.s
2348
2349 i = i + 1
2350
2351
2352def _CheckWATCHLISTSSyntax(expression, ast):
2353 if not isinstance(expression, ast.Expression):
2354 return 'WATCHLISTS file must contain a valid expression'
2355 dictionary = expression.body
2356 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2357 return 'WATCHLISTS file must have single dict with exactly two entries'
2358
2359 first_key = dictionary.keys[0]
2360 first_value = dictionary.values[0]
2361 second_key = dictionary.keys[1]
2362 second_value = dictionary.values[1]
2363
2364 if (not isinstance(first_key, ast.Str) or
2365 first_key.s != 'WATCHLIST_DEFINITIONS' or
2366 not isinstance(first_value, ast.Dict)):
2367 return (
2368 'The first entry of the dict in WATCHLISTS file must be '
2369 'WATCHLIST_DEFINITIONS dict')
2370
2371 if (not isinstance(second_key, ast.Str) or
2372 second_key.s != 'WATCHLISTS' or
2373 not isinstance(second_value, ast.Dict)):
2374 return (
2375 'The second entry of the dict in WATCHLISTS file must be '
2376 'WATCHLISTS dict')
2377
2378 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132379
2380
2381def _CheckWATCHLISTS(input_api, output_api):
2382 for f in input_api.AffectedFiles(include_deletes=False):
2383 if f.LocalPath() == 'WATCHLISTS':
2384 contents = input_api.ReadFile(f, 'r')
2385
2386 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202387 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132388 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202389 # Get an AST tree for it and scan the tree for detailed style checking.
2390 expression = input_api.ast.parse(
2391 contents, filename='WATCHLISTS', mode='eval')
2392 except ValueError as e:
2393 return [output_api.PresubmitError(
2394 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2395 except SyntaxError as e:
2396 return [output_api.PresubmitError(
2397 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2398 except TypeError as e:
2399 return [output_api.PresubmitError(
2400 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132401
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202402 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2403 if result is not None:
2404 return [output_api.PresubmitError(result)]
2405 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132406
2407 return []
2408
2409
dgnaa68d5e2015-06-10 10:08:222410def _AndroidSpecificOnUploadChecks(input_api, output_api):
2411 """Groups checks that target android code."""
2412 results = []
dgnaa68d5e2015-06-10 10:08:222413 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222414 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292415 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062416 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2417 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422418 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182419 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222420 return results
2421
2422
[email protected]22c9bd72011-03-27 16:47:392423def _CommonChecks(input_api, output_api):
2424 """Checks common to both upload and commit."""
2425 results = []
2426 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382427 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542428 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582429 results.extend(
2430 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192431 results.extend(
[email protected]760deea2013-12-10 19:33:492432 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542433 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182434 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522435 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222436 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442437 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592438 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062439 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122440 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182441 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222442 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302443 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492444 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032445 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492446 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442447 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272448 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072449 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542450 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442451 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392452 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552453 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042454 results.extend(
2455 input_api.canned_checks.CheckChangeHasNoTabs(
2456 input_api,
2457 output_api,
2458 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402459 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162460 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082461 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242462 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2463 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472464 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042465 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232466 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432467 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402468 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152469 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172470 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502471 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242472 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362473 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132474 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432475 results.extend(input_api.RunTests(
2476 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242477
2478 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2479 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2480 input_api, output_api,
2481 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382482 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392483 return results
[email protected]1f7b4172010-01-28 01:17:342484
[email protected]b337cb5b2011-01-23 21:24:052485
[email protected]b8079ae4a2012-12-05 19:56:492486def _CheckPatchFiles(input_api, output_api):
2487 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2488 if f.LocalPath().endswith(('.orig', '.rej'))]
2489 if problems:
2490 return [output_api.PresubmitError(
2491 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032492 else:
2493 return []
[email protected]b8079ae4a2012-12-05 19:56:492494
2495
Kent Tamura5a8755d2017-06-29 23:37:072496def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212497 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2498 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2499 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072500 include_re = input_api.re.compile(
2501 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2502 extension_re = input_api.re.compile(r'\.[a-z]+$')
2503 errors = []
2504 for f in input_api.AffectedFiles():
2505 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2506 continue
2507 found_line_number = None
2508 found_macro = None
2509 for line_num, line in f.ChangedContents():
2510 match = macro_re.search(line)
2511 if match:
2512 found_line_number = line_num
2513 found_macro = match.group(2)
2514 break
2515 if not found_line_number:
2516 continue
2517
2518 found_include = False
2519 for line in f.NewContents():
2520 if include_re.search(line):
2521 found_include = True
2522 break
2523 if found_include:
2524 continue
2525
2526 if not f.LocalPath().endswith('.h'):
2527 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2528 try:
2529 content = input_api.ReadFile(primary_header_path, 'r')
2530 if include_re.search(content):
2531 continue
2532 except IOError:
2533 pass
2534 errors.append('%s:%d %s macro is used without including build/'
2535 'build_config.h.'
2536 % (f.LocalPath(), found_line_number, found_macro))
2537 if errors:
2538 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2539 return []
2540
2541
[email protected]b00342e7f2013-03-26 16:21:542542def _DidYouMeanOSMacro(bad_macro):
2543 try:
2544 return {'A': 'OS_ANDROID',
2545 'B': 'OS_BSD',
2546 'C': 'OS_CHROMEOS',
2547 'F': 'OS_FREEBSD',
2548 'L': 'OS_LINUX',
2549 'M': 'OS_MACOSX',
2550 'N': 'OS_NACL',
2551 'O': 'OS_OPENBSD',
2552 'P': 'OS_POSIX',
2553 'S': 'OS_SOLARIS',
2554 'W': 'OS_WIN'}[bad_macro[3].upper()]
2555 except KeyError:
2556 return ''
2557
2558
2559def _CheckForInvalidOSMacrosInFile(input_api, f):
2560 """Check for sensible looking, totally invalid OS macros."""
2561 preprocessor_statement = input_api.re.compile(r'^\s*#')
2562 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2563 results = []
2564 for lnum, line in f.ChangedContents():
2565 if preprocessor_statement.search(line):
2566 for match in os_macro.finditer(line):
2567 if not match.group(1) in _VALID_OS_MACROS:
2568 good = _DidYouMeanOSMacro(match.group(1))
2569 did_you_mean = ' (did you mean %s?)' % good if good else ''
2570 results.append(' %s:%d %s%s' % (f.LocalPath(),
2571 lnum,
2572 match.group(1),
2573 did_you_mean))
2574 return results
2575
2576
2577def _CheckForInvalidOSMacros(input_api, output_api):
2578 """Check all affected files for invalid OS macros."""
2579 bad_macros = []
2580 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472581 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542582 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2583
2584 if not bad_macros:
2585 return []
2586
2587 return [output_api.PresubmitError(
2588 'Possibly invalid OS macro[s] found. Please fix your code\n'
2589 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2590
lliabraa35bab3932014-10-01 12:16:442591
2592def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2593 """Check all affected files for invalid "if defined" macros."""
2594 ALWAYS_DEFINED_MACROS = (
2595 "TARGET_CPU_PPC",
2596 "TARGET_CPU_PPC64",
2597 "TARGET_CPU_68K",
2598 "TARGET_CPU_X86",
2599 "TARGET_CPU_ARM",
2600 "TARGET_CPU_MIPS",
2601 "TARGET_CPU_SPARC",
2602 "TARGET_CPU_ALPHA",
2603 "TARGET_IPHONE_SIMULATOR",
2604 "TARGET_OS_EMBEDDED",
2605 "TARGET_OS_IPHONE",
2606 "TARGET_OS_MAC",
2607 "TARGET_OS_UNIX",
2608 "TARGET_OS_WIN32",
2609 )
2610 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2611 results = []
2612 for lnum, line in f.ChangedContents():
2613 for match in ifdef_macro.finditer(line):
2614 if match.group(1) in ALWAYS_DEFINED_MACROS:
2615 always_defined = ' %s is always defined. ' % match.group(1)
2616 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2617 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2618 lnum,
2619 always_defined,
2620 did_you_mean))
2621 return results
2622
2623
2624def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2625 """Check all affected files for invalid "if defined" macros."""
2626 bad_macros = []
2627 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212628 if f.LocalPath().startswith('third_party/sqlite/'):
2629 continue
lliabraa35bab3932014-10-01 12:16:442630 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2631 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2632
2633 if not bad_macros:
2634 return []
2635
2636 return [output_api.PresubmitError(
2637 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2638 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2639 bad_macros)]
2640
2641
mlamouria82272622014-09-16 18:45:042642def _CheckForIPCRules(input_api, output_api):
2643 """Check for same IPC rules described in
2644 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2645 """
2646 base_pattern = r'IPC_ENUM_TRAITS\('
2647 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2648 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2649
2650 problems = []
2651 for f in input_api.AffectedSourceFiles(None):
2652 local_path = f.LocalPath()
2653 if not local_path.endswith('.h'):
2654 continue
2655 for line_number, line in f.ChangedContents():
2656 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2657 problems.append(
2658 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2659
2660 if problems:
2661 return [output_api.PresubmitPromptWarning(
2662 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2663 else:
2664 return []
2665
[email protected]b00342e7f2013-03-26 16:21:542666
mostynbb639aca52015-01-07 20:31:232667def _CheckForWindowsLineEndings(input_api, output_api):
2668 """Check source code and known ascii text files for Windows style line
2669 endings.
2670 """
earthdok1b5e0ee2015-03-10 15:19:102671 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232672
2673 file_inclusion_pattern = (
2674 known_text_files,
2675 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2676 )
2677
mostynbb639aca52015-01-07 20:31:232678 problems = []
Andrew Grieve933d12e2017-10-30 20:22:532679 source_file_filter = lambda f: input_api.FilterSourceFile(
2680 f, white_list=file_inclusion_pattern, black_list=None)
2681 for f in input_api.AffectedSourceFiles(source_file_filter):
2682 for line_number, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:232683 if line.endswith('\r\n'):
Andrew Grieve933d12e2017-10-30 20:22:532684 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:232685
2686 if problems:
2687 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2688 'these files to contain Windows style line endings?\n' +
2689 '\n'.join(problems))]
2690
2691 return []
2692
2693
pastarmovj89f7ee12016-09-20 14:58:132694def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2695 lint_filters=None, verbose_level=None):
2696 """Checks that all source files use SYSLOG properly."""
2697 syslog_files = []
2698 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562699 for line_number, line in f.ChangedContents():
2700 if 'SYSLOG' in line:
2701 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2702
pastarmovj89f7ee12016-09-20 14:58:132703 if syslog_files:
2704 return [output_api.PresubmitPromptWarning(
2705 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2706 ' calls.\nFiles to check:\n', items=syslog_files)]
2707 return []
2708
2709
[email protected]1f7b4172010-01-28 01:17:342710def CheckChangeOnUpload(input_api, output_api):
2711 results = []
2712 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472713 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282714 results.extend(
jam93a6ee792017-02-08 23:59:222715 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192716 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222717 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132718 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162719 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542720 return results
[email protected]ca8d1982009-02-19 16:33:122721
2722
[email protected]1bfb8322014-04-23 01:02:412723def GetTryServerMasterForBot(bot):
2724 """Returns the Try Server master for the given bot.
2725
[email protected]0bb112362014-07-26 04:38:322726 It tries to guess the master from the bot name, but may still fail
2727 and return None. There is no longer a default master.
2728 """
2729 # Potentially ambiguous bot names are listed explicitly.
2730 master_map = {
tandriie5587792016-07-14 00:34:502731 'chromium_presubmit': 'master.tryserver.chromium.linux',
2732 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412733 }
[email protected]0bb112362014-07-26 04:38:322734 master = master_map.get(bot)
2735 if not master:
wnwen4fbaab82016-05-25 12:54:362736 if 'android' in bot:
tandriie5587792016-07-14 00:34:502737 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362738 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502739 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322740 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502741 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322742 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502743 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322744 return master
[email protected]1bfb8322014-04-23 01:02:412745
2746
[email protected]ca8d1982009-02-19 16:33:122747def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542748 results = []
[email protected]1f7b4172010-01-28 01:17:342749 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542750 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272751 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342752 input_api,
2753 output_api,
[email protected]2fdd1f362013-01-16 03:56:032754 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272755
jam93a6ee792017-02-08 23:59:222756 results.extend(
2757 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542758 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2759 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412760 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2761 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542762 return results