blob: 5f2a3a5bbe455dd2fcba984d78db0b94162c7df3 [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[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16453 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Sean Kau46e29bc2017-08-28 16:31:16454]
455
456
[email protected]b00342e7f2013-03-26 16:21:54457_VALID_OS_MACROS = (
458 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08459 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54460 'OS_ANDROID',
461 'OS_BSD',
462 'OS_CAT', # For testing.
463 'OS_CHROMEOS',
464 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37465 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54466 'OS_IOS',
467 'OS_LINUX',
468 'OS_MACOSX',
469 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21470 'OS_NACL_NONSFI',
471 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12472 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54473 'OS_OPENBSD',
474 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37475 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54476 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54477 'OS_WIN',
478)
479
480
agrievef32bcc72016-04-04 14:57:40481_ANDROID_SPECIFIC_PYDEPS_FILES = [
482 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04483 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58484 'build/secondary/third_party/android_platform/'
485 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19486 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40487]
488
wnwenbdc444e2016-05-25 13:44:15489
agrievef32bcc72016-04-04 14:57:40490_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40491]
492
wnwenbdc444e2016-05-25 13:44:15493
agrievef32bcc72016-04-04 14:57:40494_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
495
496
[email protected]55459852011-08-10 15:17:19497def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
498 """Attempts to prevent use of functions intended only for testing in
499 non-testing code. For now this is just a best-effort implementation
500 that ignores header files and may have some false positives. A
501 better implementation would probably need a proper C++ parser.
502 """
503 # We only scan .cc files and the like, as the declaration of
504 # for-testing functions in header files are hard to distinguish from
505 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44506 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19507
jochenc0d4808c2015-07-27 09:25:42508 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19509 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09510 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19511 exclusion_pattern = input_api.re.compile(
512 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
513 base_function_pattern, base_function_pattern))
514
515 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44516 black_list = (_EXCLUDED_PATHS +
517 _TEST_CODE_EXCLUDED_PATHS +
518 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19519 return input_api.FilterSourceFile(
520 affected_file,
521 white_list=(file_inclusion_pattern, ),
522 black_list=black_list)
523
524 problems = []
525 for f in input_api.AffectedSourceFiles(FilterFile):
526 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24527 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03528 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46529 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03530 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19531 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03532 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19533
534 if problems:
[email protected]f7051d52013-04-02 18:31:42535 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03536 else:
537 return []
[email protected]55459852011-08-10 15:17:19538
539
[email protected]10689ca2011-09-02 02:31:54540def _CheckNoIOStreamInHeaders(input_api, output_api):
541 """Checks to make sure no .h files include <iostream>."""
542 files = []
543 pattern = input_api.re.compile(r'^#include\s*<iostream>',
544 input_api.re.MULTILINE)
545 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
546 if not f.LocalPath().endswith('.h'):
547 continue
548 contents = input_api.ReadFile(f)
549 if pattern.search(contents):
550 files.append(f)
551
552 if len(files):
yolandyandaabc6d2016-04-18 18:29:39553 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06554 'Do not #include <iostream> in header files, since it inserts static '
555 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54556 '#include <ostream>. See http://crbug.com/94794',
557 files) ]
558 return []
559
560
[email protected]72df4e782012-06-21 16:28:18561def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52562 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18563 problems = []
564 for f in input_api.AffectedFiles():
565 if (not f.LocalPath().endswith(('.cc', '.mm'))):
566 continue
567
568 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04569 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18570 problems.append(' %s:%d' % (f.LocalPath(), line_num))
571
572 if not problems:
573 return []
574 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
575 '\n'.join(problems))]
576
577
danakj61c1aa22015-10-26 19:55:52578def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57579 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52580 errors = []
581 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
582 input_api.re.MULTILINE)
583 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
584 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
585 continue
586 for lnum, line in f.ChangedContents():
587 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17588 errors.append(output_api.PresubmitError(
589 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57590 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17591 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52592 return errors
593
594
mcasasb7440c282015-02-04 14:52:19595def _FindHistogramNameInLine(histogram_name, line):
596 """Tries to find a histogram name or prefix in a line."""
597 if not "affected-histogram" in line:
598 return histogram_name in line
599 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
600 # the histogram_name.
601 if not '"' in line:
602 return False
603 histogram_prefix = line.split('\"')[1]
604 return histogram_prefix in histogram_name
605
606
607def _CheckUmaHistogramChanges(input_api, output_api):
608 """Check that UMA histogram names in touched lines can still be found in other
609 lines of the patch or in histograms.xml. Note that this check would not catch
610 the reverse: changes in histograms.xml not matched in the code itself."""
611 touched_histograms = []
612 histograms_xml_modifications = []
613 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
614 for f in input_api.AffectedFiles():
615 # If histograms.xml itself is modified, keep the modified lines for later.
616 if f.LocalPath().endswith(('histograms.xml')):
617 histograms_xml_modifications = f.ChangedContents()
618 continue
619 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
620 continue
621 for line_num, line in f.ChangedContents():
622 found = pattern.search(line)
623 if found:
624 touched_histograms.append([found.group(1), f, line_num])
625
626 # Search for the touched histogram names in the local modifications to
627 # histograms.xml, and, if not found, on the base histograms.xml file.
628 unmatched_histograms = []
629 for histogram_info in touched_histograms:
630 histogram_name_found = False
631 for line_num, line in histograms_xml_modifications:
632 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
633 if histogram_name_found:
634 break
635 if not histogram_name_found:
636 unmatched_histograms.append(histogram_info)
637
eromanb90c82e7e32015-04-01 15:13:49638 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19639 problems = []
640 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49641 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19642 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45643 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19644 histogram_name_found = False
645 for line in histograms_xml:
646 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
647 if histogram_name_found:
648 break
649 if not histogram_name_found:
650 problems.append(' [%s:%d] %s' %
651 (f.LocalPath(), line_num, histogram_name))
652
653 if not problems:
654 return []
655 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
656 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49657 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19658
wnwenbdc444e2016-05-25 13:44:15659
yolandyandaabc6d2016-04-18 18:29:39660def _CheckFlakyTestUsage(input_api, output_api):
661 """Check that FlakyTest annotation is our own instead of the android one"""
662 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
663 files = []
664 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
665 if f.LocalPath().endswith('Test.java'):
666 if pattern.search(input_api.ReadFile(f)):
667 files.append(f)
668 if len(files):
669 return [output_api.PresubmitError(
670 'Use org.chromium.base.test.util.FlakyTest instead of '
671 'android.test.FlakyTest',
672 files)]
673 return []
mcasasb7440c282015-02-04 14:52:19674
wnwenbdc444e2016-05-25 13:44:15675
[email protected]8ea5d4b2011-09-13 21:49:22676def _CheckNoNewWStrings(input_api, output_api):
677 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27678 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22679 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20680 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57681 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34682 '/win/' in f.LocalPath() or
683 'chrome_elf' in f.LocalPath() or
684 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20685 continue
[email protected]8ea5d4b2011-09-13 21:49:22686
[email protected]a11dbe9b2012-08-07 01:32:58687 allowWString = False
[email protected]b5c24292011-11-28 14:38:20688 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58689 if 'presubmit: allow wstring' in line:
690 allowWString = True
691 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27692 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58693 allowWString = False
694 else:
695 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22696
[email protected]55463aa62011-10-12 00:48:27697 if not problems:
698 return []
699 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58700 ' If you are calling a cross-platform API that accepts a wstring, '
701 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27702 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22703
704
[email protected]2a8ac9c2011-10-19 17:20:44705def _CheckNoDEPSGIT(input_api, output_api):
706 """Make sure .DEPS.git is never modified manually."""
707 if any(f.LocalPath().endswith('.DEPS.git') for f in
708 input_api.AffectedFiles()):
709 return [output_api.PresubmitError(
710 'Never commit changes to .DEPS.git. This file is maintained by an\n'
711 'automated system based on what\'s in DEPS and your changes will be\n'
712 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34713 '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:44714 'for more information')]
715 return []
716
717
tandriief664692014-09-23 14:51:47718def _CheckValidHostsInDEPS(input_api, output_api):
719 """Checks that DEPS file deps are from allowed_hosts."""
720 # Run only if DEPS file has been modified to annoy fewer bystanders.
721 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
722 return []
723 # Outsource work to gclient verify
724 try:
725 input_api.subprocess.check_output(['gclient', 'verify'])
726 return []
727 except input_api.subprocess.CalledProcessError, error:
728 return [output_api.PresubmitError(
729 'DEPS file must have only git dependencies.',
730 long_text=error.output)]
731
732
[email protected]127f18ec2012-06-16 05:05:59733def _CheckNoBannedFunctions(input_api, output_api):
734 """Make sure that banned functions are not used."""
735 warnings = []
736 errors = []
737
wnwenbdc444e2016-05-25 13:44:15738 def IsBlacklisted(affected_file, blacklist):
739 local_path = affected_file.LocalPath()
740 for item in blacklist:
741 if input_api.re.match(item, local_path):
742 return True
743 return False
744
745 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
746 matched = False
747 if func_name[0:1] == '/':
748 regex = func_name[1:]
749 if input_api.re.search(regex, line):
750 matched = True
751 elif func_name in line:
dchenge07de812016-06-20 19:27:17752 matched = True
wnwenbdc444e2016-05-25 13:44:15753 if matched:
dchenge07de812016-06-20 19:27:17754 problems = warnings
wnwenbdc444e2016-05-25 13:44:15755 if error:
dchenge07de812016-06-20 19:27:17756 problems = errors
wnwenbdc444e2016-05-25 13:44:15757 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
758 for message_line in message:
759 problems.append(' %s' % message_line)
760
Eric Stevensona9a980972017-09-23 00:04:41761 file_filter = lambda f: f.LocalPath().endswith(('.java'))
762 for f in input_api.AffectedFiles(file_filter=file_filter):
763 for line_num, line in f.ChangedContents():
764 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
765 CheckForMatch(f, line_num, line, func_name, message, error)
766
[email protected]127f18ec2012-06-16 05:05:59767 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
768 for f in input_api.AffectedFiles(file_filter=file_filter):
769 for line_num, line in f.ChangedContents():
770 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15771 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59772
773 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
774 for f in input_api.AffectedFiles(file_filter=file_filter):
775 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49776 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49777 if IsBlacklisted(f, excluded_paths):
778 continue
wnwenbdc444e2016-05-25 13:44:15779 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59780
781 result = []
782 if (warnings):
783 result.append(output_api.PresubmitPromptWarning(
784 'Banned functions were used.\n' + '\n'.join(warnings)))
785 if (errors):
786 result.append(output_api.PresubmitError(
787 'Banned functions were used.\n' + '\n'.join(errors)))
788 return result
789
790
[email protected]6c063c62012-07-11 19:11:06791def _CheckNoPragmaOnce(input_api, output_api):
792 """Make sure that banned functions are not used."""
793 files = []
794 pattern = input_api.re.compile(r'^#pragma\s+once',
795 input_api.re.MULTILINE)
796 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
797 if not f.LocalPath().endswith('.h'):
798 continue
799 contents = input_api.ReadFile(f)
800 if pattern.search(contents):
801 files.append(f)
802
803 if files:
804 return [output_api.PresubmitError(
805 'Do not use #pragma once in header files.\n'
806 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
807 files)]
808 return []
809
[email protected]127f18ec2012-06-16 05:05:59810
[email protected]e7479052012-09-19 00:26:12811def _CheckNoTrinaryTrueFalse(input_api, output_api):
812 """Checks to make sure we don't introduce use of foo ? true : false."""
813 problems = []
814 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
815 for f in input_api.AffectedFiles():
816 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
817 continue
818
819 for line_num, line in f.ChangedContents():
820 if pattern.match(line):
821 problems.append(' %s:%d' % (f.LocalPath(), line_num))
822
823 if not problems:
824 return []
825 return [output_api.PresubmitPromptWarning(
826 'Please consider avoiding the "? true : false" pattern if possible.\n' +
827 '\n'.join(problems))]
828
829
[email protected]55f9f382012-07-31 11:02:18830def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28831 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18832 change. Breaking - rules is an error, breaking ! rules is a
833 warning.
834 """
mohan.reddyf21db962014-10-16 12:26:47835 import sys
[email protected]55f9f382012-07-31 11:02:18836 # We need to wait until we have an input_api object and use this
837 # roundabout construct to import checkdeps because this file is
838 # eval-ed and thus doesn't have __file__.
839 original_sys_path = sys.path
840 try:
841 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47842 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18843 import checkdeps
844 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:24845 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:28846 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18847 from rules import Rule
848 finally:
849 # Restore sys.path to what it was before.
850 sys.path = original_sys_path
851
852 added_includes = []
rhalavati08acd232017-04-03 07:23:28853 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:24854 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:18855 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28856 if CppChecker.IsCppFile(f.LocalPath()):
857 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08858 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:28859 elif ProtoChecker.IsProtoFile(f.LocalPath()):
860 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08861 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:24862 elif JavaChecker.IsJavaFile(f.LocalPath()):
863 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08864 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18865
[email protected]26385172013-05-09 23:11:35866 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18867
868 error_descriptions = []
869 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28870 error_subjects = set()
871 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18872 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
873 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:08874 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18875 description_with_path = '%s\n %s' % (path, rule_description)
876 if rule_type == Rule.DISALLOW:
877 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28878 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18879 else:
880 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28881 warning_subjects.add("#includes")
882
883 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
884 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:08885 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:28886 description_with_path = '%s\n %s' % (path, rule_description)
887 if rule_type == Rule.DISALLOW:
888 error_descriptions.append(description_with_path)
889 error_subjects.add("imports")
890 else:
891 warning_descriptions.append(description_with_path)
892 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18893
Jinsuk Kim5a092672017-10-24 22:42:24894 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
895 added_java_imports):
Andrew Grieve085f29f2017-11-02 09:14:08896 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:24897 description_with_path = '%s\n %s' % (path, rule_description)
898 if rule_type == Rule.DISALLOW:
899 error_descriptions.append(description_with_path)
900 error_subjects.add("imports")
901 else:
902 warning_descriptions.append(description_with_path)
903 warning_subjects.add("imports")
904
[email protected]55f9f382012-07-31 11:02:18905 results = []
906 if error_descriptions:
907 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28908 'You added one or more %s that violate checkdeps rules.'
909 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18910 error_descriptions))
911 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42912 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28913 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18914 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28915 '%s? See relevant DEPS file(s) for details and contacts.' %
916 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18917 warning_descriptions))
918 return results
919
920
[email protected]fbcafe5a2012-08-08 15:31:22921def _CheckFilePermissions(input_api, output_api):
922 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15923 if input_api.platform == 'win32':
924 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29925 checkperms_tool = input_api.os_path.join(
926 input_api.PresubmitLocalPath(),
927 'tools', 'checkperms', 'checkperms.py')
928 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47929 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:39930 with input_api.CreateTemporaryFile() as file_list:
931 for f in input_api.AffectedFiles():
932 # checkperms.py file/directory arguments must be relative to the
933 # repository.
934 file_list.write(f.LocalPath() + '\n')
935 file_list.close()
936 args += ['--file-list', file_list.name]
937 try:
938 input_api.subprocess.check_output(args)
939 return []
940 except input_api.subprocess.CalledProcessError as error:
941 return [output_api.PresubmitError(
942 'checkperms.py failed:',
943 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22944
945
robertocn832f5992017-01-04 19:01:30946def _CheckTeamTags(input_api, output_api):
947 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
948 checkteamtags_tool = input_api.os_path.join(
949 input_api.PresubmitLocalPath(),
950 'tools', 'checkteamtags', 'checkteamtags.py')
951 args = [input_api.python_executable, checkteamtags_tool,
952 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22953 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30954 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
955 'OWNERS']
956 try:
957 if files:
958 input_api.subprocess.check_output(args + files)
959 return []
960 except input_api.subprocess.CalledProcessError as error:
961 return [output_api.PresubmitError(
962 'checkteamtags.py failed:',
963 long_text=error.output)]
964
965
[email protected]c8278b32012-10-30 20:35:49966def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
967 """Makes sure we don't include ui/aura/window_property.h
968 in header files.
969 """
970 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
971 errors = []
972 for f in input_api.AffectedFiles():
973 if not f.LocalPath().endswith('.h'):
974 continue
975 for line_num, line in f.ChangedContents():
976 if pattern.match(line):
977 errors.append(' %s:%d' % (f.LocalPath(), line_num))
978
979 results = []
980 if errors:
981 results.append(output_api.PresubmitError(
982 'Header files should not include ui/aura/window_property.h', errors))
983 return results
984
985
[email protected]70ca77752012-11-20 03:45:03986def _CheckForVersionControlConflictsInFile(input_api, f):
987 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
988 errors = []
989 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23990 if f.LocalPath().endswith('.md'):
991 # First-level headers in markdown look a lot like version control
992 # conflict markers. http://daringfireball.net/projects/markdown/basics
993 continue
[email protected]70ca77752012-11-20 03:45:03994 if pattern.match(line):
995 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
996 return errors
997
998
999def _CheckForVersionControlConflicts(input_api, output_api):
1000 """Usually this is not intentional and will cause a compile failure."""
1001 errors = []
1002 for f in input_api.AffectedFiles():
1003 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1004
1005 results = []
1006 if errors:
1007 results.append(output_api.PresubmitError(
1008 'Version control conflict markers found, please resolve.', errors))
1009 return results
1010
estadee17314a02017-01-12 16:22:161011def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1012 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1013 errors = []
1014 for f in input_api.AffectedFiles():
1015 for line_num, line in f.ChangedContents():
1016 if pattern.search(line):
1017 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1018
1019 results = []
1020 if errors:
1021 results.append(output_api.PresubmitPromptWarning(
1022 'Found Google support URL addressed by answer number. Please replace with '
1023 'a p= identifier instead. See crbug.com/679462\n', errors))
1024 return results
1025
[email protected]70ca77752012-11-20 03:45:031026
[email protected]06e6d0ff2012-12-11 01:36:441027def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1028 def FilterFile(affected_file):
1029 """Filter function for use with input_api.AffectedSourceFiles,
1030 below. This filters out everything except non-test files from
1031 top-level directories that generally speaking should not hard-code
1032 service URLs (e.g. src/android_webview/, src/content/ and others).
1033 """
1034 return input_api.FilterSourceFile(
1035 affected_file,
[email protected]78bb39d62012-12-11 15:11:561036 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441037 black_list=(_EXCLUDED_PATHS +
1038 _TEST_CODE_EXCLUDED_PATHS +
1039 input_api.DEFAULT_BLACK_LIST))
1040
reillyi38965732015-11-16 18:27:331041 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1042 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461043 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1044 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441045 problems = [] # items are (filename, line_number, line)
1046 for f in input_api.AffectedSourceFiles(FilterFile):
1047 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461048 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441049 problems.append((f.LocalPath(), line_num, line))
1050
1051 if problems:
[email protected]f7051d52013-04-02 18:31:421052 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441053 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581054 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441055 [' %s:%d: %s' % (
1056 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031057 else:
1058 return []
[email protected]06e6d0ff2012-12-11 01:36:441059
1060
[email protected]d2530012013-01-25 16:39:271061def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1062 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311063 The native_client_sdk directory is excluded because it has auto-generated PNG
1064 files for documentation.
[email protected]d2530012013-01-25 16:39:271065 """
[email protected]d2530012013-01-25 16:39:271066 errors = []
binji0dcdf342014-12-12 18:32:311067 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1068 black_list = (r'^native_client_sdk[\\\/]',)
1069 file_filter = lambda f: input_api.FilterSourceFile(
1070 f, white_list=white_list, black_list=black_list)
1071 for f in input_api.AffectedFiles(include_deletes=False,
1072 file_filter=file_filter):
1073 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271074
1075 results = []
1076 if errors:
1077 results.append(output_api.PresubmitError(
1078 'The name of PNG files should not have abbreviations. \n'
1079 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1080 'Contact [email protected] if you have questions.', errors))
1081 return results
1082
1083
Daniel Cheng4dcdb6b2017-04-13 08:30:171084def _ExtractAddRulesFromParsedDeps(parsed_deps):
1085 """Extract the rules that add dependencies from a parsed DEPS file.
1086
1087 Args:
1088 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1089 add_rules = set()
1090 add_rules.update([
1091 rule[1:] for rule in parsed_deps.get('include_rules', [])
1092 if rule.startswith('+') or rule.startswith('!')
1093 ])
1094 for specific_file, rules in parsed_deps.get('specific_include_rules',
1095 {}).iteritems():
1096 add_rules.update([
1097 rule[1:] for rule in rules
1098 if rule.startswith('+') or rule.startswith('!')
1099 ])
1100 return add_rules
1101
1102
1103def _ParseDeps(contents):
1104 """Simple helper for parsing DEPS files."""
1105 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171106 class _VarImpl:
1107
1108 def __init__(self, local_scope):
1109 self._local_scope = local_scope
1110
1111 def Lookup(self, var_name):
1112 """Implements the Var syntax."""
1113 try:
1114 return self._local_scope['vars'][var_name]
1115 except KeyError:
1116 raise Exception('Var is not defined: %s' % var_name)
1117
1118 local_scope = {}
1119 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171120 'Var': _VarImpl(local_scope).Lookup,
1121 }
1122 exec contents in global_scope, local_scope
1123 return local_scope
1124
1125
1126def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081127 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411128 a set of DEPS entries that we should look up.
1129
1130 For a directory (rather than a specific filename) we fake a path to
1131 a specific filename by adding /DEPS. This is chosen as a file that
1132 will seldom or never be subject to per-file include_rules.
1133 """
[email protected]2b438d62013-11-14 17:54:141134 # We ignore deps entries on auto-generated directories.
1135 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081136
Daniel Cheng4dcdb6b2017-04-13 08:30:171137 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1138 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1139
1140 added_deps = new_deps.difference(old_deps)
1141
[email protected]2b438d62013-11-14 17:54:141142 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171143 for added_dep in added_deps:
1144 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1145 continue
1146 # Assume that a rule that ends in .h is a rule for a specific file.
1147 if added_dep.endswith('.h'):
1148 results.add(added_dep)
1149 else:
1150 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081151 return results
1152
1153
[email protected]e871964c2013-05-13 14:14:551154def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1155 """When a dependency prefixed with + is added to a DEPS file, we
1156 want to make sure that the change is reviewed by an OWNER of the
1157 target file or directory, to avoid layering violations from being
1158 introduced. This check verifies that this happens.
1159 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171160 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241161
1162 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191163 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241164 for f in input_api.AffectedFiles(include_deletes=False,
1165 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551166 filename = input_api.os_path.basename(f.LocalPath())
1167 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171168 virtual_depended_on_files.update(_CalculateAddedDeps(
1169 input_api.os_path,
1170 '\n'.join(f.OldContents()),
1171 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551172
[email protected]e871964c2013-05-13 14:14:551173 if not virtual_depended_on_files:
1174 return []
1175
1176 if input_api.is_committing:
1177 if input_api.tbr:
1178 return [output_api.PresubmitNotifyResult(
1179 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271180 if input_api.dry_run:
1181 return [output_api.PresubmitNotifyResult(
1182 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551183 if not input_api.change.issue:
1184 return [output_api.PresubmitError(
1185 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401186 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551187 output = output_api.PresubmitError
1188 else:
1189 output = output_api.PresubmitNotifyResult
1190
1191 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501192 owner_email, reviewers = (
1193 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1194 input_api,
1195 owners_db.email_regexp,
1196 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551197
1198 owner_email = owner_email or input_api.change.author_email
1199
[email protected]de4f7d22013-05-23 14:27:461200 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511201 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461202 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551203 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1204 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411205
1206 # We strip the /DEPS part that was added by
1207 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1208 # directory.
1209 def StripDeps(path):
1210 start_deps = path.rfind('/DEPS')
1211 if start_deps != -1:
1212 return path[:start_deps]
1213 else:
1214 return path
1215 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551216 for path in missing_files]
1217
1218 if unapproved_dependencies:
1219 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151220 output('You need LGTM from owners of depends-on paths in DEPS that were '
1221 'modified in this CL:\n %s' %
1222 '\n '.join(sorted(unapproved_dependencies)))]
1223 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1224 output_list.append(output(
1225 'Suggested missing target path OWNERS:\n %s' %
1226 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551227 return output_list
1228
1229 return []
1230
1231
[email protected]85218562013-11-22 07:41:401232def _CheckSpamLogging(input_api, output_api):
1233 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1234 black_list = (_EXCLUDED_PATHS +
1235 _TEST_CODE_EXCLUDED_PATHS +
1236 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501237 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191238 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481239 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461240 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121241 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1242 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581243 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591244 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161245 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031246 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151247 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1248 r"^chromecast[\\\/]",
1249 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481250 r"^components[\\\/]browser_watcher[\\\/]"
1251 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311252 r"^components[\\\/]html_viewer[\\\/]"
1253 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461254 # TODO(peter): Remove this exception. https://crbug.com/534537
1255 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1256 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251257 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1258 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241259 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111260 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151261 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111262 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521263 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501264 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361265 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311266 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131267 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001268 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441269 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451270 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021271 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351272 r"dump_file_system.cc$",
1273 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401274 source_file_filter = lambda x: input_api.FilterSourceFile(
1275 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1276
thomasanderson625d3932017-03-29 07:16:581277 log_info = set([])
1278 printf = set([])
[email protected]85218562013-11-22 07:41:401279
1280 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581281 for _, line in f.ChangedContents():
1282 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1283 log_info.add(f.LocalPath())
1284 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1285 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371286
thomasanderson625d3932017-03-29 07:16:581287 if input_api.re.search(r"\bprintf\(", line):
1288 printf.add(f.LocalPath())
1289 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1290 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401291
1292 if log_info:
1293 return [output_api.PresubmitError(
1294 'These files spam the console log with LOG(INFO):',
1295 items=log_info)]
1296 if printf:
1297 return [output_api.PresubmitError(
1298 'These files spam the console log with printf/fprintf:',
1299 items=printf)]
1300 return []
1301
1302
[email protected]49aa76a2013-12-04 06:59:161303def _CheckForAnonymousVariables(input_api, output_api):
1304 """These types are all expected to hold locks while in scope and
1305 so should never be anonymous (which causes them to be immediately
1306 destroyed)."""
1307 they_who_must_be_named = [
1308 'base::AutoLock',
1309 'base::AutoReset',
1310 'base::AutoUnlock',
1311 'SkAutoAlphaRestore',
1312 'SkAutoBitmapShaderInstall',
1313 'SkAutoBlitterChoose',
1314 'SkAutoBounderCommit',
1315 'SkAutoCallProc',
1316 'SkAutoCanvasRestore',
1317 'SkAutoCommentBlock',
1318 'SkAutoDescriptor',
1319 'SkAutoDisableDirectionCheck',
1320 'SkAutoDisableOvalCheck',
1321 'SkAutoFree',
1322 'SkAutoGlyphCache',
1323 'SkAutoHDC',
1324 'SkAutoLockColors',
1325 'SkAutoLockPixels',
1326 'SkAutoMalloc',
1327 'SkAutoMaskFreeImage',
1328 'SkAutoMutexAcquire',
1329 'SkAutoPathBoundsUpdate',
1330 'SkAutoPDFRelease',
1331 'SkAutoRasterClipValidate',
1332 'SkAutoRef',
1333 'SkAutoTime',
1334 'SkAutoTrace',
1335 'SkAutoUnref',
1336 ]
1337 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1338 # bad: base::AutoLock(lock.get());
1339 # not bad: base::AutoLock lock(lock.get());
1340 bad_pattern = input_api.re.compile(anonymous)
1341 # good: new base::AutoLock(lock.get())
1342 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1343 errors = []
1344
1345 for f in input_api.AffectedFiles():
1346 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1347 continue
1348 for linenum, line in f.ChangedContents():
1349 if bad_pattern.search(line) and not good_pattern.search(line):
1350 errors.append('%s:%d' % (f.LocalPath(), linenum))
1351
1352 if errors:
1353 return [output_api.PresubmitError(
1354 'These lines create anonymous variables that need to be named:',
1355 items=errors)]
1356 return []
1357
1358
[email protected]999261d2014-03-03 20:08:081359def _CheckUserActionUpdate(input_api, output_api):
1360 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521361 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081362 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521363 # If actions.xml is already included in the changelist, the PRESUBMIT
1364 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081365 return []
1366
[email protected]999261d2014-03-03 20:08:081367 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1368 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521369 current_actions = None
[email protected]999261d2014-03-03 20:08:081370 for f in input_api.AffectedFiles(file_filter=file_filter):
1371 for line_num, line in f.ChangedContents():
1372 match = input_api.re.search(action_re, line)
1373 if match:
[email protected]2f92dec2014-03-07 19:21:521374 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1375 # loaded only once.
1376 if not current_actions:
1377 with open('tools/metrics/actions/actions.xml') as actions_f:
1378 current_actions = actions_f.read()
1379 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081380 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521381 action = 'name="{0}"'.format(action_name)
1382 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081383 return [output_api.PresubmitPromptWarning(
1384 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521385 'tools/metrics/actions/actions.xml. Please run '
1386 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081387 % (f.LocalPath(), line_num, action_name))]
1388 return []
1389
1390
Daniel Cheng13ca61a882017-08-25 15:11:251391def _ImportJSONCommentEater(input_api):
1392 import sys
1393 sys.path = sys.path + [input_api.os_path.join(
1394 input_api.PresubmitLocalPath(),
1395 'tools', 'json_comment_eater')]
1396 import json_comment_eater
1397 return json_comment_eater
1398
1399
[email protected]99171a92014-06-03 08:44:471400def _GetJSONParseError(input_api, filename, eat_comments=True):
1401 try:
1402 contents = input_api.ReadFile(filename)
1403 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251404 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131405 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471406
1407 input_api.json.loads(contents)
1408 except ValueError as e:
1409 return e
1410 return None
1411
1412
1413def _GetIDLParseError(input_api, filename):
1414 try:
1415 contents = input_api.ReadFile(filename)
1416 idl_schema = input_api.os_path.join(
1417 input_api.PresubmitLocalPath(),
1418 'tools', 'json_schema_compiler', 'idl_schema.py')
1419 process = input_api.subprocess.Popen(
1420 [input_api.python_executable, idl_schema],
1421 stdin=input_api.subprocess.PIPE,
1422 stdout=input_api.subprocess.PIPE,
1423 stderr=input_api.subprocess.PIPE,
1424 universal_newlines=True)
1425 (_, error) = process.communicate(input=contents)
1426 return error or None
1427 except ValueError as e:
1428 return e
1429
1430
1431def _CheckParseErrors(input_api, output_api):
1432 """Check that IDL and JSON files do not contain syntax errors."""
1433 actions = {
1434 '.idl': _GetIDLParseError,
1435 '.json': _GetJSONParseError,
1436 }
[email protected]99171a92014-06-03 08:44:471437 # Most JSON files are preprocessed and support comments, but these do not.
1438 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491439 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471440 ]
1441 # Only run IDL checker on files in these directories.
1442 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491443 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1444 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471445 ]
1446
1447 def get_action(affected_file):
1448 filename = affected_file.LocalPath()
1449 return actions.get(input_api.os_path.splitext(filename)[1])
1450
[email protected]99171a92014-06-03 08:44:471451 def FilterFile(affected_file):
1452 action = get_action(affected_file)
1453 if not action:
1454 return False
1455 path = affected_file.LocalPath()
1456
Sean Kau46e29bc2017-08-28 16:31:161457 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471458 return False
1459
1460 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161461 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471462 return False
1463 return True
1464
1465 results = []
1466 for affected_file in input_api.AffectedFiles(
1467 file_filter=FilterFile, include_deletes=False):
1468 action = get_action(affected_file)
1469 kwargs = {}
1470 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161471 _MatchesFile(input_api, json_no_comments_patterns,
1472 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471473 kwargs['eat_comments'] = False
1474 parse_error = action(input_api,
1475 affected_file.AbsoluteLocalPath(),
1476 **kwargs)
1477 if parse_error:
1478 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1479 (affected_file.LocalPath(), parse_error)))
1480 return results
1481
1482
[email protected]760deea2013-12-10 19:33:491483def _CheckJavaStyle(input_api, output_api):
1484 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471485 import sys
[email protected]760deea2013-12-10 19:33:491486 original_sys_path = sys.path
1487 try:
1488 sys.path = sys.path + [input_api.os_path.join(
1489 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1490 import checkstyle
1491 finally:
1492 # Restore sys.path to what it was before.
1493 sys.path = original_sys_path
1494
1495 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091496 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511497 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491498
1499
Sean Kau46e29bc2017-08-28 16:31:161500def _MatchesFile(input_api, patterns, path):
1501 for pattern in patterns:
1502 if input_api.re.search(pattern, path):
1503 return True
1504 return False
1505
1506
dchenge07de812016-06-20 19:27:171507def _CheckIpcOwners(input_api, output_api):
1508 """Checks that affected files involving IPC have an IPC OWNERS rule.
1509
1510 Whether or not a file affects IPC is determined by a simple whitelist of
1511 filename patterns."""
1512 file_patterns = [
palmerb19a0932017-01-24 04:00:311513 # Legacy IPC:
dchenge07de812016-06-20 19:27:171514 '*_messages.cc',
1515 '*_messages*.h',
1516 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311517 # Mojo IPC:
dchenge07de812016-06-20 19:27:171518 '*.mojom',
1519 '*_struct_traits*.*',
1520 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311521 '*.typemap',
1522 # Android native IPC:
1523 '*.aidl',
1524 # Blink uses a different file naming convention:
1525 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171526 '*StructTraits*.*',
1527 '*TypeConverter*.*',
1528 ]
1529
scottmg7a6ed5ba2016-11-04 18:22:041530 # These third_party directories do not contain IPCs, but contain files
1531 # matching the above patterns, which trigger false positives.
1532 exclude_paths = [
1533 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291534 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041535 ]
1536
dchenge07de812016-06-20 19:27:171537 # Dictionary mapping an OWNERS file path to Patterns.
1538 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1539 # rules ) to a PatternEntry.
1540 # PatternEntry is a dictionary with two keys:
1541 # - 'files': the files that are matched by this pattern
1542 # - 'rules': the per-file rules needed for this pattern
1543 # For example, if we expect OWNERS file to contain rules for *.mojom and
1544 # *_struct_traits*.*, Patterns might look like this:
1545 # {
1546 # '*.mojom': {
1547 # 'files': ...,
1548 # 'rules': [
1549 # 'per-file *.mojom=set noparent',
1550 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1551 # ],
1552 # },
1553 # '*_struct_traits*.*': {
1554 # 'files': ...,
1555 # 'rules': [
1556 # 'per-file *_struct_traits*.*=set noparent',
1557 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1558 # ],
1559 # },
1560 # }
1561 to_check = {}
1562
Daniel Cheng13ca61a882017-08-25 15:11:251563 def AddPatternToCheck(input_file, pattern):
1564 owners_file = input_api.os_path.join(
1565 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1566 if owners_file not in to_check:
1567 to_check[owners_file] = {}
1568 if pattern not in to_check[owners_file]:
1569 to_check[owners_file][pattern] = {
1570 'files': [],
1571 'rules': [
1572 'per-file %s=set noparent' % pattern,
1573 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1574 ]
1575 }
1576 to_check[owners_file][pattern]['files'].append(f)
1577
dchenge07de812016-06-20 19:27:171578 # Iterate through the affected files to see what we actually need to check
1579 # for. We should only nag patch authors about per-file rules if a file in that
1580 # directory would match that pattern. If a directory only contains *.mojom
1581 # files and no *_messages*.h files, we should only nag about rules for
1582 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251583 for f in input_api.AffectedFiles(include_deletes=False):
1584 # Manifest files don't have a strong naming convention. Instead, scan
1585 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161586 if (f.LocalPath().endswith('.json') and
1587 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1588 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251589 json_comment_eater = _ImportJSONCommentEater(input_api)
1590 mostly_json_lines = '\n'.join(f.NewContents())
1591 # Comments aren't allowed in strict JSON, so filter them out.
1592 json_lines = json_comment_eater.Nom(mostly_json_lines)
1593 json_content = input_api.json.loads(json_lines)
1594 if 'interface_provider_specs' in json_content:
1595 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171596 for pattern in file_patterns:
1597 if input_api.fnmatch.fnmatch(
1598 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041599 skip = False
1600 for exclude in exclude_paths:
1601 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1602 skip = True
1603 break
1604 if skip:
1605 continue
Daniel Cheng13ca61a882017-08-25 15:11:251606 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171607 break
1608
1609 # Now go through the OWNERS files we collected, filtering out rules that are
1610 # already present in that OWNERS file.
1611 for owners_file, patterns in to_check.iteritems():
1612 try:
1613 with file(owners_file) as f:
1614 lines = set(f.read().splitlines())
1615 for entry in patterns.itervalues():
1616 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1617 ]
1618 except IOError:
1619 # No OWNERS file, so all the rules are definitely missing.
1620 continue
1621
1622 # All the remaining lines weren't found in OWNERS files, so emit an error.
1623 errors = []
1624 for owners_file, patterns in to_check.iteritems():
1625 missing_lines = []
1626 files = []
1627 for pattern, entry in patterns.iteritems():
1628 missing_lines.extend(entry['rules'])
1629 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1630 if missing_lines:
1631 errors.append(
Daniel Cheng52111692017-06-14 08:00:591632 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171633 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1634
1635 results = []
1636 if errors:
vabrf5ce3bf92016-07-11 14:52:411637 if input_api.is_committing:
1638 output = output_api.PresubmitError
1639 else:
1640 output = output_api.PresubmitPromptWarning
1641 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591642 'Found OWNERS files that need to be updated for IPC security ' +
1643 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171644 long_text='\n\n'.join(errors)))
1645
1646 return results
1647
1648
jbriance9e12f162016-11-25 07:57:501649def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311650 """Checks that added or removed lines in non third party affected
1651 header files do not lead to new useless class or struct forward
1652 declaration.
jbriance9e12f162016-11-25 07:57:501653 """
1654 results = []
1655 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1656 input_api.re.MULTILINE)
1657 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1658 input_api.re.MULTILINE)
1659 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311660 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191661 not f.LocalPath().startswith('third_party/blink') and
1662 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311663 not f.LocalPath().startswith('third_party/WebKit') and
1664 not f.LocalPath().startswith('third_party\\WebKit')):
1665 continue
1666
jbriance9e12f162016-11-25 07:57:501667 if not f.LocalPath().endswith('.h'):
1668 continue
1669
1670 contents = input_api.ReadFile(f)
1671 fwd_decls = input_api.re.findall(class_pattern, contents)
1672 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1673
1674 useless_fwd_decls = []
1675 for decl in fwd_decls:
1676 count = sum(1 for _ in input_api.re.finditer(
1677 r'\b%s\b' % input_api.re.escape(decl), contents))
1678 if count == 1:
1679 useless_fwd_decls.append(decl)
1680
1681 if not useless_fwd_decls:
1682 continue
1683
1684 for line in f.GenerateScmDiff().splitlines():
1685 if (line.startswith('-') and not line.startswith('--') or
1686 line.startswith('+') and not line.startswith('++')):
1687 for decl in useless_fwd_decls:
1688 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1689 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241690 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501691 (f.LocalPath(), decl)))
1692 useless_fwd_decls.remove(decl)
1693
1694 return results
1695
1696
dskiba88634f4e2015-08-14 23:03:291697def _CheckAndroidToastUsage(input_api, output_api):
1698 """Checks that code uses org.chromium.ui.widget.Toast instead of
1699 android.widget.Toast (Chromium Toast doesn't force hardware
1700 acceleration on low-end devices, saving memory).
1701 """
1702 toast_import_pattern = input_api.re.compile(
1703 r'^import android\.widget\.Toast;$')
1704
1705 errors = []
1706
1707 sources = lambda affected_file: input_api.FilterSourceFile(
1708 affected_file,
1709 black_list=(_EXCLUDED_PATHS +
1710 _TEST_CODE_EXCLUDED_PATHS +
1711 input_api.DEFAULT_BLACK_LIST +
1712 (r'^chromecast[\\\/].*',
1713 r'^remoting[\\\/].*')),
1714 white_list=(r'.*\.java$',))
1715
1716 for f in input_api.AffectedSourceFiles(sources):
1717 for line_num, line in f.ChangedContents():
1718 if toast_import_pattern.search(line):
1719 errors.append("%s:%d" % (f.LocalPath(), line_num))
1720
1721 results = []
1722
1723 if errors:
1724 results.append(output_api.PresubmitError(
1725 'android.widget.Toast usage is detected. Android toasts use hardware'
1726 ' acceleration, and can be\ncostly on low-end devices. Please use'
1727 ' org.chromium.ui.widget.Toast instead.\n'
1728 'Contact [email protected] if you have any questions.',
1729 errors))
1730
1731 return results
1732
1733
dgnaa68d5e2015-06-10 10:08:221734def _CheckAndroidCrLogUsage(input_api, output_api):
1735 """Checks that new logs using org.chromium.base.Log:
1736 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511737 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221738 """
pkotwicza1dd0b002016-05-16 14:41:041739
torne89540622017-03-24 19:41:301740 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041741 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301742 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041743 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301744 # WebView license viewer code cannot depend on //base; used in stub APK.
1745 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1746 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041747 ]
1748
dgnaa68d5e2015-06-10 10:08:221749 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121750 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1751 class_in_base_pattern = input_api.re.compile(
1752 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1753 has_some_log_import_pattern = input_api.re.compile(
1754 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221755 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121756 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221757 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511758 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221759 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221760
Vincent Scheib16d7b272015-09-15 18:09:071761 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221762 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041763 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1764 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121765
dgnaa68d5e2015-06-10 10:08:221766 tag_decl_errors = []
1767 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121768 tag_errors = []
dgn38736db2015-09-18 19:20:511769 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121770 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221771
1772 for f in input_api.AffectedSourceFiles(sources):
1773 file_content = input_api.ReadFile(f)
1774 has_modified_logs = False
1775
1776 # Per line checks
dgn87d9fb62015-06-12 09:15:121777 if (cr_log_import_pattern.search(file_content) or
1778 (class_in_base_pattern.search(file_content) and
1779 not has_some_log_import_pattern.search(file_content))):
1780 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221781 for line_num, line in f.ChangedContents():
1782
1783 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121784 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221785 if match:
1786 has_modified_logs = True
1787
1788 # Make sure it uses "TAG"
1789 if not match.group('tag') == 'TAG':
1790 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121791 else:
1792 # Report non cr Log function calls in changed lines
1793 for line_num, line in f.ChangedContents():
1794 if log_call_pattern.search(line):
1795 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221796
1797 # Per file checks
1798 if has_modified_logs:
1799 # Make sure the tag is using the "cr" prefix and is not too long
1800 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511801 tag_name = match.group('name') if match else None
1802 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221803 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511804 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221805 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511806 elif '.' in tag_name:
1807 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221808
1809 results = []
1810 if tag_decl_errors:
1811 results.append(output_api.PresubmitPromptWarning(
1812 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511813 '"private static final String TAG = "<package tag>".\n'
1814 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221815 tag_decl_errors))
1816
1817 if tag_length_errors:
1818 results.append(output_api.PresubmitError(
1819 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511820 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221821 tag_length_errors))
1822
1823 if tag_errors:
1824 results.append(output_api.PresubmitPromptWarning(
1825 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1826 tag_errors))
1827
dgn87d9fb62015-06-12 09:15:121828 if util_log_errors:
dgn4401aa52015-04-29 16:26:171829 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121830 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1831 util_log_errors))
1832
dgn38736db2015-09-18 19:20:511833 if tag_with_dot_errors:
1834 results.append(output_api.PresubmitPromptWarning(
1835 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1836 tag_with_dot_errors))
1837
dgn4401aa52015-04-29 16:26:171838 return results
1839
1840
Yoland Yanb92fa522017-08-28 17:37:061841def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1842 """Checks that junit.framework.* is no longer used."""
1843 deprecated_junit_framework_pattern = input_api.re.compile(
1844 r'^import junit\.framework\..*;',
1845 input_api.re.MULTILINE)
1846 sources = lambda x: input_api.FilterSourceFile(
1847 x, white_list=(r'.*\.java$',), black_list=None)
1848 errors = []
1849 for f in input_api.AffectedFiles(sources):
1850 for line_num, line in f.ChangedContents():
1851 if deprecated_junit_framework_pattern.search(line):
1852 errors.append("%s:%d" % (f.LocalPath(), line_num))
1853
1854 results = []
1855 if errors:
1856 results.append(output_api.PresubmitError(
1857 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1858 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1859 ' if you have any question.', errors))
1860 return results
1861
1862
1863def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1864 """Checks that if new Java test classes have inheritance.
1865 Either the new test class is JUnit3 test or it is a JUnit4 test class
1866 with a base class, either case is undesirable.
1867 """
1868 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1869
1870 sources = lambda x: input_api.FilterSourceFile(
1871 x, white_list=(r'.*Test\.java$',), black_list=None)
1872 errors = []
1873 for f in input_api.AffectedFiles(sources):
1874 if not f.OldContents():
1875 class_declaration_start_flag = False
1876 for line_num, line in f.ChangedContents():
1877 if class_declaration_pattern.search(line):
1878 class_declaration_start_flag = True
1879 if class_declaration_start_flag and ' extends ' in line:
1880 errors.append('%s:%d' % (f.LocalPath(), line_num))
1881 if '{' in line:
1882 class_declaration_start_flag = False
1883
1884 results = []
1885 if errors:
1886 results.append(output_api.PresubmitPromptWarning(
1887 'The newly created files include Test classes that inherits from base'
1888 ' class. Please do not use inheritance in JUnit4 tests or add new'
1889 ' JUnit3 tests. Contact [email protected] if you have any'
1890 ' questions.', errors))
1891 return results
1892
yolandyan45001472016-12-21 21:12:421893def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1894 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1895 deprecated_annotation_import_pattern = input_api.re.compile(
1896 r'^import android\.test\.suitebuilder\.annotation\..*;',
1897 input_api.re.MULTILINE)
1898 sources = lambda x: input_api.FilterSourceFile(
1899 x, white_list=(r'.*\.java$',), black_list=None)
1900 errors = []
1901 for f in input_api.AffectedFiles(sources):
1902 for line_num, line in f.ChangedContents():
1903 if deprecated_annotation_import_pattern.search(line):
1904 errors.append("%s:%d" % (f.LocalPath(), line_num))
1905
1906 results = []
1907 if errors:
1908 results.append(output_api.PresubmitError(
1909 'Annotations in android.test.suitebuilder.annotation have been'
1910 ' deprecated since API level 24. Please use android.support.test.filters'
1911 ' from //third_party/android_support_test_runner:runner_java instead.'
1912 ' Contact [email protected] if you have any questions.', errors))
1913 return results
1914
1915
agrieve7b6479d82015-10-07 14:24:221916def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1917 """Checks if MDPI assets are placed in a correct directory."""
1918 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1919 ('/res/drawable/' in f.LocalPath() or
1920 '/res/drawable-ldrtl/' in f.LocalPath()))
1921 errors = []
1922 for f in input_api.AffectedFiles(include_deletes=False,
1923 file_filter=file_filter):
1924 errors.append(' %s' % f.LocalPath())
1925
1926 results = []
1927 if errors:
1928 results.append(output_api.PresubmitError(
1929 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1930 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1931 '/res/drawable-ldrtl/.\n'
1932 'Contact [email protected] if you have questions.', errors))
1933 return results
1934
1935
Nate Fischer535972b2017-09-16 01:06:181936def _CheckAndroidWebkitImports(input_api, output_api):
1937 """Checks that code uses org.chromium.base.Callback instead of
1938 android.widget.ValueCallback except in the WebView glue layer.
1939 """
1940 valuecallback_import_pattern = input_api.re.compile(
1941 r'^import android\.webkit\.ValueCallback;$')
1942
1943 errors = []
1944
1945 sources = lambda affected_file: input_api.FilterSourceFile(
1946 affected_file,
1947 black_list=(_EXCLUDED_PATHS +
1948 _TEST_CODE_EXCLUDED_PATHS +
1949 input_api.DEFAULT_BLACK_LIST +
1950 (r'^android_webview[\\\/]glue[\\\/].*',)),
1951 white_list=(r'.*\.java$',))
1952
1953 for f in input_api.AffectedSourceFiles(sources):
1954 for line_num, line in f.ChangedContents():
1955 if valuecallback_import_pattern.search(line):
1956 errors.append("%s:%d" % (f.LocalPath(), line_num))
1957
1958 results = []
1959
1960 if errors:
1961 results.append(output_api.PresubmitError(
1962 'android.webkit.ValueCallback usage is detected outside of the glue'
1963 ' layer. To stay compatible with the support library, android.webkit.*'
1964 ' classes should only be used inside the glue layer and'
1965 ' org.chromium.base.Callback should be used instead.',
1966 errors))
1967
1968 return results
1969
1970
agrievef32bcc72016-04-04 14:57:401971class PydepsChecker(object):
1972 def __init__(self, input_api, pydeps_files):
1973 self._file_cache = {}
1974 self._input_api = input_api
1975 self._pydeps_files = pydeps_files
1976
1977 def _LoadFile(self, path):
1978 """Returns the list of paths within a .pydeps file relative to //."""
1979 if path not in self._file_cache:
1980 with open(path) as f:
1981 self._file_cache[path] = f.read()
1982 return self._file_cache[path]
1983
1984 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1985 """Returns an interable of paths within the .pydep, relativized to //."""
1986 os_path = self._input_api.os_path
1987 pydeps_dir = os_path.dirname(pydeps_path)
1988 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1989 if not l.startswith('*'))
1990 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1991
1992 def _CreateFilesToPydepsMap(self):
1993 """Returns a map of local_path -> list_of_pydeps."""
1994 ret = {}
1995 for pydep_local_path in self._pydeps_files:
1996 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1997 ret.setdefault(path, []).append(pydep_local_path)
1998 return ret
1999
2000 def ComputeAffectedPydeps(self):
2001 """Returns an iterable of .pydeps files that might need regenerating."""
2002 affected_pydeps = set()
2003 file_to_pydeps_map = None
2004 for f in self._input_api.AffectedFiles(include_deletes=True):
2005 local_path = f.LocalPath()
2006 if local_path == 'DEPS':
2007 return self._pydeps_files
2008 elif local_path.endswith('.pydeps'):
2009 if local_path in self._pydeps_files:
2010 affected_pydeps.add(local_path)
2011 elif local_path.endswith('.py'):
2012 if file_to_pydeps_map is None:
2013 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2014 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2015 return affected_pydeps
2016
2017 def DetermineIfStale(self, pydeps_path):
2018 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412019 import difflib
agrievef32bcc72016-04-04 14:57:402020 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2021 cmd = old_pydeps_data[1][1:].strip()
John Budorickab2fa102017-10-06 16:59:492022 env = {
2023 'PYTHONDONTWRITEBYTECODE': '1'
2024 }
agrievef32bcc72016-04-04 14:57:402025 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorickab2fa102017-10-06 16:59:492026 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412027 old_contents = old_pydeps_data[2:]
2028 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402029 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412030 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402031
2032
2033def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2034 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:002035 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:282036 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
2037 # Mac, so skip it on other platforms.
2038 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002039 return []
agrievef32bcc72016-04-04 14:57:402040 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
2041 is_android = input_api.os_path.exists('third_party/android_tools')
2042 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2043 results = []
2044 # First, check for new / deleted .pydeps.
2045 for f in input_api.AffectedFiles(include_deletes=True):
2046 if f.LocalPath().endswith('.pydeps'):
2047 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2048 results.append(output_api.PresubmitError(
2049 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2050 'remove %s' % f.LocalPath()))
2051 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2052 results.append(output_api.PresubmitError(
2053 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2054 'include %s' % f.LocalPath()))
2055
2056 if results:
2057 return results
2058
2059 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2060
2061 for pydep_path in checker.ComputeAffectedPydeps():
2062 try:
phajdan.jr0d9878552016-11-04 10:49:412063 result = checker.DetermineIfStale(pydep_path)
2064 if result:
2065 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402066 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412067 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2068 'To regenerate, run:\n\n %s' %
2069 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402070 except input_api.subprocess.CalledProcessError as error:
2071 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2072 long_text=error.output)]
2073
2074 return results
2075
2076
glidere61efad2015-02-18 17:39:432077def _CheckSingletonInHeaders(input_api, output_api):
2078 """Checks to make sure no header files have |Singleton<|."""
2079 def FileFilter(affected_file):
2080 # It's ok for base/memory/singleton.h to have |Singleton<|.
2081 black_list = (_EXCLUDED_PATHS +
2082 input_api.DEFAULT_BLACK_LIST +
2083 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2084 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2085
sergeyu34d21222015-09-16 00:11:442086 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432087 files = []
2088 for f in input_api.AffectedSourceFiles(FileFilter):
2089 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2090 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2091 contents = input_api.ReadFile(f)
2092 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242093 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432094 pattern.search(line)):
2095 files.append(f)
2096 break
2097
2098 if files:
yolandyandaabc6d2016-04-18 18:29:392099 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442100 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432101 'Please move them to an appropriate source file so that the ' +
2102 'template gets instantiated in a single compilation unit.',
2103 files) ]
2104 return []
2105
2106
[email protected]fd20b902014-05-09 02:14:532107_DEPRECATED_CSS = [
2108 # Values
2109 ( "-webkit-box", "flex" ),
2110 ( "-webkit-inline-box", "inline-flex" ),
2111 ( "-webkit-flex", "flex" ),
2112 ( "-webkit-inline-flex", "inline-flex" ),
2113 ( "-webkit-min-content", "min-content" ),
2114 ( "-webkit-max-content", "max-content" ),
2115
2116 # Properties
2117 ( "-webkit-background-clip", "background-clip" ),
2118 ( "-webkit-background-origin", "background-origin" ),
2119 ( "-webkit-background-size", "background-size" ),
2120 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442121 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532122
2123 # Functions
2124 ( "-webkit-gradient", "gradient" ),
2125 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2126 ( "-webkit-linear-gradient", "linear-gradient" ),
2127 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2128 ( "-webkit-radial-gradient", "radial-gradient" ),
2129 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2130]
2131
dbeam1ec68ac2016-12-15 05:22:242132def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532133 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252134 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342135 documentation and iOS CSS for dom distiller
2136 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252137 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532138 results = []
dbeam070cfe62014-10-22 06:44:022139 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252140 black_list = (_EXCLUDED_PATHS +
2141 _TEST_CODE_EXCLUDED_PATHS +
2142 input_api.DEFAULT_BLACK_LIST +
2143 (r"^chrome/common/extensions/docs",
2144 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342145 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442146 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252147 r"^native_client_sdk"))
2148 file_filter = lambda f: input_api.FilterSourceFile(
2149 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532150 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2151 for line_num, line in fpath.ChangedContents():
2152 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022153 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532154 results.append(output_api.PresubmitError(
2155 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2156 (fpath.LocalPath(), line_num, deprecated_value, value)))
2157 return results
2158
mohan.reddyf21db962014-10-16 12:26:472159
dbeam070cfe62014-10-22 06:44:022160_DEPRECATED_JS = [
2161 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2162 ( "__defineGetter__", "Object.defineProperty" ),
2163 ( "__defineSetter__", "Object.defineProperty" ),
2164]
2165
dbeam1ec68ac2016-12-15 05:22:242166def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022167 """Make sure that we don't use deprecated JS in Chrome code."""
2168 results = []
2169 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2170 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2171 input_api.DEFAULT_BLACK_LIST)
2172 file_filter = lambda f: input_api.FilterSourceFile(
2173 f, white_list=file_inclusion_pattern, black_list=black_list)
2174 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2175 for lnum, line in fpath.ChangedContents():
2176 for (deprecated, replacement) in _DEPRECATED_JS:
2177 if deprecated in line:
2178 results.append(output_api.PresubmitError(
2179 "%s:%d: Use of deprecated JS %s, use %s instead" %
2180 (fpath.LocalPath(), lnum, deprecated, replacement)))
2181 return results
2182
dpapadd651231d82017-07-21 02:44:472183def _CheckForRiskyJsArrowFunction(line_number, line):
2184 if ' => ' in line:
2185 return "line %d, is using an => (arrow) function\n %s\n" % (
2186 line_number, line)
2187 return ''
2188
2189def _CheckForRiskyJsConstLet(input_api, line_number, line):
2190 if input_api.re.match('^\s*(const|let)\s', line):
2191 return "line %d, is using const/let keyword\n %s\n" % (
2192 line_number, line)
2193 return ''
dbeam070cfe62014-10-22 06:44:022194
dbeam1ec68ac2016-12-15 05:22:242195def _CheckForRiskyJsFeatures(input_api, output_api):
2196 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002197 # 'ui/webui/resources/cr_components are not allowed on ios'
2198 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572199 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002200 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472201 results = []
dbeam1ec68ac2016-12-15 05:22:242202 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472203 arrow_error_lines = []
2204 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242205 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472206 arrow_error_lines += filter(None, [
2207 _CheckForRiskyJsArrowFunction(lnum, line),
2208 ])
dbeam1ec68ac2016-12-15 05:22:242209
dpapadd651231d82017-07-21 02:44:472210 const_let_error_lines += filter(None, [
2211 _CheckForRiskyJsConstLet(input_api, lnum, line),
2212 ])
dbeam1ec68ac2016-12-15 05:22:242213
dpapadd651231d82017-07-21 02:44:472214 if arrow_error_lines:
2215 arrow_error_lines = map(
2216 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2217 results.append(
2218 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2219"""
2220Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242221%s
2222Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2223https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472224""" % f.LocalPath()
2225 ])))
dbeam1ec68ac2016-12-15 05:22:242226
dpapadd651231d82017-07-21 02:44:472227 if const_let_error_lines:
2228 const_let_error_lines = map(
2229 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2230 results.append(
2231 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2232"""
2233Use of const/let keywords detected in:
2234%s
2235Please ensure your code does not run on iOS9 because const/let is not fully
2236supported.
2237https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2238https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2239""" % f.LocalPath()
2240 ])))
2241
2242 return results
dbeam1ec68ac2016-12-15 05:22:242243
rlanday6802cf632017-05-30 17:48:362244def _CheckForRelativeIncludes(input_api, output_api):
2245 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2246 import sys
2247 original_sys_path = sys.path
2248 try:
2249 sys.path = sys.path + [input_api.os_path.join(
2250 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2251 from cpp_checker import CppChecker
2252 finally:
2253 # Restore sys.path to what it was before.
2254 sys.path = original_sys_path
2255
2256 bad_files = {}
2257 for f in input_api.AffectedFiles(include_deletes=False):
2258 if (f.LocalPath().startswith('third_party') and
2259 not f.LocalPath().startswith('third_party/WebKit') and
2260 not f.LocalPath().startswith('third_party\\WebKit')):
2261 continue
2262
2263 if not CppChecker.IsCppFile(f.LocalPath()):
2264 continue
2265
2266 relative_includes = [line for line_num, line in f.ChangedContents()
2267 if "#include" in line and "../" in line]
2268 if not relative_includes:
2269 continue
2270 bad_files[f.LocalPath()] = relative_includes
2271
2272 if not bad_files:
2273 return []
2274
2275 error_descriptions = []
2276 for file_path, bad_lines in bad_files.iteritems():
2277 error_description = file_path
2278 for line in bad_lines:
2279 error_description += '\n ' + line
2280 error_descriptions.append(error_description)
2281
2282 results = []
2283 results.append(output_api.PresubmitError(
2284 'You added one or more relative #include paths (including "../").\n'
2285 'These shouldn\'t be used because they can be used to include headers\n'
2286 'from code that\'s not correctly specified as a dependency in the\n'
2287 'relevant BUILD.gn file(s).',
2288 error_descriptions))
2289
2290 return results
2291
Takeshi Yoshinoe387aa32017-08-02 13:16:132292
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202293def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2294 if not isinstance(key, ast.Str):
2295 return 'Key at line %d must be a string literal' % key.lineno
2296 if not isinstance(value, ast.Dict):
2297 return 'Value at line %d must be a dict' % value.lineno
2298 if len(value.keys) != 1:
2299 return 'Dict at line %d must have single entry' % value.lineno
2300 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2301 return (
2302 'Entry at line %d must have a string literal \'filepath\' as key' %
2303 value.lineno)
2304 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132305
Takeshi Yoshinoe387aa32017-08-02 13:16:132306
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202307def _CheckWatchlistsEntrySyntax(key, value, ast):
2308 if not isinstance(key, ast.Str):
2309 return 'Key at line %d must be a string literal' % key.lineno
2310 if not isinstance(value, ast.List):
2311 return 'Value at line %d must be a list' % value.lineno
2312 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132313
Takeshi Yoshinoe387aa32017-08-02 13:16:132314
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202315def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2316 mismatch_template = (
2317 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2318 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132319
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202320 i = 0
2321 last_key = ''
2322 while True:
2323 if i >= len(wd_dict.keys):
2324 if i >= len(w_dict.keys):
2325 return None
2326 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2327 elif i >= len(w_dict.keys):
2328 return (
2329 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132330
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202331 wd_key = wd_dict.keys[i]
2332 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132333
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202334 result = _CheckWatchlistDefinitionsEntrySyntax(
2335 wd_key, wd_dict.values[i], ast)
2336 if result is not None:
2337 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132338
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202339 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2340 if result is not None:
2341 return 'Bad entry in WATCHLISTS dict: %s' % result
2342
2343 if wd_key.s != w_key.s:
2344 return mismatch_template % (
2345 '%s at line %d' % (wd_key.s, wd_key.lineno),
2346 '%s at line %d' % (w_key.s, w_key.lineno))
2347
2348 if wd_key.s < last_key:
2349 return (
2350 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2351 (wd_key.lineno, w_key.lineno))
2352 last_key = wd_key.s
2353
2354 i = i + 1
2355
2356
2357def _CheckWATCHLISTSSyntax(expression, ast):
2358 if not isinstance(expression, ast.Expression):
2359 return 'WATCHLISTS file must contain a valid expression'
2360 dictionary = expression.body
2361 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2362 return 'WATCHLISTS file must have single dict with exactly two entries'
2363
2364 first_key = dictionary.keys[0]
2365 first_value = dictionary.values[0]
2366 second_key = dictionary.keys[1]
2367 second_value = dictionary.values[1]
2368
2369 if (not isinstance(first_key, ast.Str) or
2370 first_key.s != 'WATCHLIST_DEFINITIONS' or
2371 not isinstance(first_value, ast.Dict)):
2372 return (
2373 'The first entry of the dict in WATCHLISTS file must be '
2374 'WATCHLIST_DEFINITIONS dict')
2375
2376 if (not isinstance(second_key, ast.Str) or
2377 second_key.s != 'WATCHLISTS' or
2378 not isinstance(second_value, ast.Dict)):
2379 return (
2380 'The second entry of the dict in WATCHLISTS file must be '
2381 'WATCHLISTS dict')
2382
2383 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132384
2385
2386def _CheckWATCHLISTS(input_api, output_api):
2387 for f in input_api.AffectedFiles(include_deletes=False):
2388 if f.LocalPath() == 'WATCHLISTS':
2389 contents = input_api.ReadFile(f, 'r')
2390
2391 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202392 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132393 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202394 # Get an AST tree for it and scan the tree for detailed style checking.
2395 expression = input_api.ast.parse(
2396 contents, filename='WATCHLISTS', mode='eval')
2397 except ValueError as e:
2398 return [output_api.PresubmitError(
2399 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2400 except SyntaxError as e:
2401 return [output_api.PresubmitError(
2402 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2403 except TypeError as e:
2404 return [output_api.PresubmitError(
2405 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132406
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202407 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2408 if result is not None:
2409 return [output_api.PresubmitError(result)]
2410 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132411
2412 return []
2413
2414
dgnaa68d5e2015-06-10 10:08:222415def _AndroidSpecificOnUploadChecks(input_api, output_api):
2416 """Groups checks that target android code."""
2417 results = []
dgnaa68d5e2015-06-10 10:08:222418 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222419 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292420 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062421 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2422 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422423 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182424 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222425 return results
2426
2427
[email protected]22c9bd72011-03-27 16:47:392428def _CommonChecks(input_api, output_api):
2429 """Checks common to both upload and commit."""
2430 results = []
2431 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382432 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542433 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582434 results.extend(
2435 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192436 results.extend(
[email protected]760deea2013-12-10 19:33:492437 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542438 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182439 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522440 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222441 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442442 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592443 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062444 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122445 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182446 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222447 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302448 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492449 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032450 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492451 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442452 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272453 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072454 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542455 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442456 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392457 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552458 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042459 results.extend(
2460 input_api.canned_checks.CheckChangeHasNoTabs(
2461 input_api,
2462 output_api,
2463 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402464 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162465 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082466 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242467 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2468 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472469 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042470 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232471 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432472 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402473 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152474 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172475 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502476 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242477 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362478 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132479 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432480 results.extend(input_api.RunTests(
2481 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242482
2483 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2484 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2485 input_api, output_api,
2486 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382487 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392488 return results
[email protected]1f7b4172010-01-28 01:17:342489
[email protected]b337cb5b2011-01-23 21:24:052490
[email protected]b8079ae4a2012-12-05 19:56:492491def _CheckPatchFiles(input_api, output_api):
2492 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2493 if f.LocalPath().endswith(('.orig', '.rej'))]
2494 if problems:
2495 return [output_api.PresubmitError(
2496 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032497 else:
2498 return []
[email protected]b8079ae4a2012-12-05 19:56:492499
2500
Kent Tamura5a8755d2017-06-29 23:37:072501def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212502 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2503 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2504 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072505 include_re = input_api.re.compile(
2506 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2507 extension_re = input_api.re.compile(r'\.[a-z]+$')
2508 errors = []
2509 for f in input_api.AffectedFiles():
2510 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2511 continue
2512 found_line_number = None
2513 found_macro = None
2514 for line_num, line in f.ChangedContents():
2515 match = macro_re.search(line)
2516 if match:
2517 found_line_number = line_num
2518 found_macro = match.group(2)
2519 break
2520 if not found_line_number:
2521 continue
2522
2523 found_include = False
2524 for line in f.NewContents():
2525 if include_re.search(line):
2526 found_include = True
2527 break
2528 if found_include:
2529 continue
2530
2531 if not f.LocalPath().endswith('.h'):
2532 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2533 try:
2534 content = input_api.ReadFile(primary_header_path, 'r')
2535 if include_re.search(content):
2536 continue
2537 except IOError:
2538 pass
2539 errors.append('%s:%d %s macro is used without including build/'
2540 'build_config.h.'
2541 % (f.LocalPath(), found_line_number, found_macro))
2542 if errors:
2543 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2544 return []
2545
2546
[email protected]b00342e7f2013-03-26 16:21:542547def _DidYouMeanOSMacro(bad_macro):
2548 try:
2549 return {'A': 'OS_ANDROID',
2550 'B': 'OS_BSD',
2551 'C': 'OS_CHROMEOS',
2552 'F': 'OS_FREEBSD',
2553 'L': 'OS_LINUX',
2554 'M': 'OS_MACOSX',
2555 'N': 'OS_NACL',
2556 'O': 'OS_OPENBSD',
2557 'P': 'OS_POSIX',
2558 'S': 'OS_SOLARIS',
2559 'W': 'OS_WIN'}[bad_macro[3].upper()]
2560 except KeyError:
2561 return ''
2562
2563
2564def _CheckForInvalidOSMacrosInFile(input_api, f):
2565 """Check for sensible looking, totally invalid OS macros."""
2566 preprocessor_statement = input_api.re.compile(r'^\s*#')
2567 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2568 results = []
2569 for lnum, line in f.ChangedContents():
2570 if preprocessor_statement.search(line):
2571 for match in os_macro.finditer(line):
2572 if not match.group(1) in _VALID_OS_MACROS:
2573 good = _DidYouMeanOSMacro(match.group(1))
2574 did_you_mean = ' (did you mean %s?)' % good if good else ''
2575 results.append(' %s:%d %s%s' % (f.LocalPath(),
2576 lnum,
2577 match.group(1),
2578 did_you_mean))
2579 return results
2580
2581
2582def _CheckForInvalidOSMacros(input_api, output_api):
2583 """Check all affected files for invalid OS macros."""
2584 bad_macros = []
2585 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472586 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542587 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2588
2589 if not bad_macros:
2590 return []
2591
2592 return [output_api.PresubmitError(
2593 'Possibly invalid OS macro[s] found. Please fix your code\n'
2594 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2595
lliabraa35bab3932014-10-01 12:16:442596
2597def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2598 """Check all affected files for invalid "if defined" macros."""
2599 ALWAYS_DEFINED_MACROS = (
2600 "TARGET_CPU_PPC",
2601 "TARGET_CPU_PPC64",
2602 "TARGET_CPU_68K",
2603 "TARGET_CPU_X86",
2604 "TARGET_CPU_ARM",
2605 "TARGET_CPU_MIPS",
2606 "TARGET_CPU_SPARC",
2607 "TARGET_CPU_ALPHA",
2608 "TARGET_IPHONE_SIMULATOR",
2609 "TARGET_OS_EMBEDDED",
2610 "TARGET_OS_IPHONE",
2611 "TARGET_OS_MAC",
2612 "TARGET_OS_UNIX",
2613 "TARGET_OS_WIN32",
2614 )
2615 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2616 results = []
2617 for lnum, line in f.ChangedContents():
2618 for match in ifdef_macro.finditer(line):
2619 if match.group(1) in ALWAYS_DEFINED_MACROS:
2620 always_defined = ' %s is always defined. ' % match.group(1)
2621 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2622 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2623 lnum,
2624 always_defined,
2625 did_you_mean))
2626 return results
2627
2628
2629def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2630 """Check all affected files for invalid "if defined" macros."""
2631 bad_macros = []
2632 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212633 if f.LocalPath().startswith('third_party/sqlite/'):
2634 continue
lliabraa35bab3932014-10-01 12:16:442635 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2636 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2637
2638 if not bad_macros:
2639 return []
2640
2641 return [output_api.PresubmitError(
2642 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2643 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2644 bad_macros)]
2645
2646
mlamouria82272622014-09-16 18:45:042647def _CheckForIPCRules(input_api, output_api):
2648 """Check for same IPC rules described in
2649 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2650 """
2651 base_pattern = r'IPC_ENUM_TRAITS\('
2652 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2653 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2654
2655 problems = []
2656 for f in input_api.AffectedSourceFiles(None):
2657 local_path = f.LocalPath()
2658 if not local_path.endswith('.h'):
2659 continue
2660 for line_number, line in f.ChangedContents():
2661 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2662 problems.append(
2663 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2664
2665 if problems:
2666 return [output_api.PresubmitPromptWarning(
2667 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2668 else:
2669 return []
2670
[email protected]b00342e7f2013-03-26 16:21:542671
mostynbb639aca52015-01-07 20:31:232672def _CheckForWindowsLineEndings(input_api, output_api):
2673 """Check source code and known ascii text files for Windows style line
2674 endings.
2675 """
earthdok1b5e0ee2015-03-10 15:19:102676 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232677
2678 file_inclusion_pattern = (
2679 known_text_files,
2680 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2681 )
2682
mostynbb639aca52015-01-07 20:31:232683 problems = []
Andrew Grieve933d12e2017-10-30 20:22:532684 source_file_filter = lambda f: input_api.FilterSourceFile(
2685 f, white_list=file_inclusion_pattern, black_list=None)
2686 for f in input_api.AffectedSourceFiles(source_file_filter):
2687 for line_number, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:232688 if line.endswith('\r\n'):
Andrew Grieve933d12e2017-10-30 20:22:532689 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:232690
2691 if problems:
2692 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2693 'these files to contain Windows style line endings?\n' +
2694 '\n'.join(problems))]
2695
2696 return []
2697
2698
pastarmovj89f7ee12016-09-20 14:58:132699def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2700 lint_filters=None, verbose_level=None):
2701 """Checks that all source files use SYSLOG properly."""
2702 syslog_files = []
2703 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562704 for line_number, line in f.ChangedContents():
2705 if 'SYSLOG' in line:
2706 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2707
pastarmovj89f7ee12016-09-20 14:58:132708 if syslog_files:
2709 return [output_api.PresubmitPromptWarning(
2710 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2711 ' calls.\nFiles to check:\n', items=syslog_files)]
2712 return []
2713
2714
[email protected]1f7b4172010-01-28 01:17:342715def CheckChangeOnUpload(input_api, output_api):
2716 results = []
2717 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472718 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282719 results.extend(
jam93a6ee792017-02-08 23:59:222720 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192721 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222722 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132723 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162724 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542725 return results
[email protected]ca8d1982009-02-19 16:33:122726
2727
[email protected]1bfb8322014-04-23 01:02:412728def GetTryServerMasterForBot(bot):
2729 """Returns the Try Server master for the given bot.
2730
[email protected]0bb112362014-07-26 04:38:322731 It tries to guess the master from the bot name, but may still fail
2732 and return None. There is no longer a default master.
2733 """
2734 # Potentially ambiguous bot names are listed explicitly.
2735 master_map = {
tandriie5587792016-07-14 00:34:502736 'chromium_presubmit': 'master.tryserver.chromium.linux',
2737 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412738 }
[email protected]0bb112362014-07-26 04:38:322739 master = master_map.get(bot)
2740 if not master:
wnwen4fbaab82016-05-25 12:54:362741 if 'android' in bot:
tandriie5587792016-07-14 00:34:502742 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362743 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502744 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322745 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502746 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322747 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502748 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322749 return master
[email protected]1bfb8322014-04-23 01:02:412750
2751
[email protected]ca8d1982009-02-19 16:33:122752def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542753 results = []
[email protected]1f7b4172010-01-28 01:17:342754 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542755 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272756 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342757 input_api,
2758 output_api,
[email protected]2fdd1f362013-01-16 03:56:032759 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272760
jam93a6ee792017-02-08 23:59:222761 results.extend(
2762 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542763 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2764 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412765 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2766 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542767 return results