blob: cb960bd06f0c94dcb7408ae386974948a01bc45c [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
Shenghua Zhangbfaa38b82017-11-16 21:58:02447_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
448 r".*[\\\/]BuildHooksAndroidImpl\.java",
449 r".*[\\\/]LicenseContentProvider\.java",
450]
[email protected]127f18ec2012-06-16 05:05:59451
Sean Kau46e29bc2017-08-28 16:31:16452# These paths contain test data and other known invalid JSON files.
453_KNOWN_INVALID_JSON_FILE_PATTERNS = [
454 r'test[\\\/]data[\\\/]',
455 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
456 r'^third_party[\\\/]protobuf[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16457 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Sean Kau46e29bc2017-08-28 16:31:16458]
459
460
[email protected]b00342e7f2013-03-26 16:21:54461_VALID_OS_MACROS = (
462 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08463 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54464 'OS_ANDROID',
465 'OS_BSD',
466 'OS_CAT', # For testing.
467 'OS_CHROMEOS',
468 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37469 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54470 'OS_IOS',
471 'OS_LINUX',
472 'OS_MACOSX',
473 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21474 'OS_NACL_NONSFI',
475 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12476 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54477 'OS_OPENBSD',
478 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37479 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54480 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54481 'OS_WIN',
482)
483
484
agrievef32bcc72016-04-04 14:57:40485_ANDROID_SPECIFIC_PYDEPS_FILES = [
486 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04487 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58488 'build/secondary/third_party/android_platform/'
489 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19490 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40491]
492
wnwenbdc444e2016-05-25 13:44:15493
agrievef32bcc72016-04-04 14:57:40494_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40495]
496
wnwenbdc444e2016-05-25 13:44:15497
agrievef32bcc72016-04-04 14:57:40498_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
499
500
[email protected]55459852011-08-10 15:17:19501def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
502 """Attempts to prevent use of functions intended only for testing in
503 non-testing code. For now this is just a best-effort implementation
504 that ignores header files and may have some false positives. A
505 better implementation would probably need a proper C++ parser.
506 """
507 # We only scan .cc files and the like, as the declaration of
508 # for-testing functions in header files are hard to distinguish from
509 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44510 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19511
jochenc0d4808c2015-07-27 09:25:42512 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19513 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09514 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19515 exclusion_pattern = input_api.re.compile(
516 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
517 base_function_pattern, base_function_pattern))
518
519 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44520 black_list = (_EXCLUDED_PATHS +
521 _TEST_CODE_EXCLUDED_PATHS +
522 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19523 return input_api.FilterSourceFile(
524 affected_file,
525 white_list=(file_inclusion_pattern, ),
526 black_list=black_list)
527
528 problems = []
529 for f in input_api.AffectedSourceFiles(FilterFile):
530 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24531 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03532 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46533 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03534 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19535 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03536 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19537
538 if problems:
[email protected]f7051d52013-04-02 18:31:42539 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03540 else:
541 return []
[email protected]55459852011-08-10 15:17:19542
543
[email protected]10689ca2011-09-02 02:31:54544def _CheckNoIOStreamInHeaders(input_api, output_api):
545 """Checks to make sure no .h files include <iostream>."""
546 files = []
547 pattern = input_api.re.compile(r'^#include\s*<iostream>',
548 input_api.re.MULTILINE)
549 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
550 if not f.LocalPath().endswith('.h'):
551 continue
552 contents = input_api.ReadFile(f)
553 if pattern.search(contents):
554 files.append(f)
555
556 if len(files):
yolandyandaabc6d2016-04-18 18:29:39557 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06558 'Do not #include <iostream> in header files, since it inserts static '
559 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54560 '#include <ostream>. See http://crbug.com/94794',
561 files) ]
562 return []
563
564
[email protected]72df4e782012-06-21 16:28:18565def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52566 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18567 problems = []
568 for f in input_api.AffectedFiles():
569 if (not f.LocalPath().endswith(('.cc', '.mm'))):
570 continue
571
572 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04573 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18574 problems.append(' %s:%d' % (f.LocalPath(), line_num))
575
576 if not problems:
577 return []
578 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
579 '\n'.join(problems))]
580
581
danakj61c1aa22015-10-26 19:55:52582def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57583 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52584 errors = []
585 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
586 input_api.re.MULTILINE)
587 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
588 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
589 continue
590 for lnum, line in f.ChangedContents():
591 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17592 errors.append(output_api.PresubmitError(
593 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57594 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17595 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52596 return errors
597
598
mcasasb7440c282015-02-04 14:52:19599def _FindHistogramNameInLine(histogram_name, line):
600 """Tries to find a histogram name or prefix in a line."""
601 if not "affected-histogram" in line:
602 return histogram_name in line
603 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
604 # the histogram_name.
605 if not '"' in line:
606 return False
607 histogram_prefix = line.split('\"')[1]
608 return histogram_prefix in histogram_name
609
610
611def _CheckUmaHistogramChanges(input_api, output_api):
612 """Check that UMA histogram names in touched lines can still be found in other
613 lines of the patch or in histograms.xml. Note that this check would not catch
614 the reverse: changes in histograms.xml not matched in the code itself."""
615 touched_histograms = []
616 histograms_xml_modifications = []
617 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
618 for f in input_api.AffectedFiles():
619 # If histograms.xml itself is modified, keep the modified lines for later.
620 if f.LocalPath().endswith(('histograms.xml')):
621 histograms_xml_modifications = f.ChangedContents()
622 continue
623 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
624 continue
625 for line_num, line in f.ChangedContents():
626 found = pattern.search(line)
627 if found:
628 touched_histograms.append([found.group(1), f, line_num])
629
630 # Search for the touched histogram names in the local modifications to
631 # histograms.xml, and, if not found, on the base histograms.xml file.
632 unmatched_histograms = []
633 for histogram_info in touched_histograms:
634 histogram_name_found = False
635 for line_num, line in histograms_xml_modifications:
636 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
637 if histogram_name_found:
638 break
639 if not histogram_name_found:
640 unmatched_histograms.append(histogram_info)
641
eromanb90c82e7e32015-04-01 15:13:49642 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19643 problems = []
644 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49645 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19646 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45647 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19648 histogram_name_found = False
649 for line in histograms_xml:
650 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
651 if histogram_name_found:
652 break
653 if not histogram_name_found:
654 problems.append(' [%s:%d] %s' %
655 (f.LocalPath(), line_num, histogram_name))
656
657 if not problems:
658 return []
659 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
660 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49661 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19662
wnwenbdc444e2016-05-25 13:44:15663
yolandyandaabc6d2016-04-18 18:29:39664def _CheckFlakyTestUsage(input_api, output_api):
665 """Check that FlakyTest annotation is our own instead of the android one"""
666 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
667 files = []
668 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
669 if f.LocalPath().endswith('Test.java'):
670 if pattern.search(input_api.ReadFile(f)):
671 files.append(f)
672 if len(files):
673 return [output_api.PresubmitError(
674 'Use org.chromium.base.test.util.FlakyTest instead of '
675 'android.test.FlakyTest',
676 files)]
677 return []
mcasasb7440c282015-02-04 14:52:19678
wnwenbdc444e2016-05-25 13:44:15679
[email protected]8ea5d4b2011-09-13 21:49:22680def _CheckNoNewWStrings(input_api, output_api):
681 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27682 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22683 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20684 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57685 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34686 '/win/' in f.LocalPath() or
687 'chrome_elf' in f.LocalPath() or
688 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20689 continue
[email protected]8ea5d4b2011-09-13 21:49:22690
[email protected]a11dbe9b2012-08-07 01:32:58691 allowWString = False
[email protected]b5c24292011-11-28 14:38:20692 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58693 if 'presubmit: allow wstring' in line:
694 allowWString = True
695 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27696 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58697 allowWString = False
698 else:
699 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22700
[email protected]55463aa62011-10-12 00:48:27701 if not problems:
702 return []
703 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58704 ' If you are calling a cross-platform API that accepts a wstring, '
705 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27706 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22707
708
[email protected]2a8ac9c2011-10-19 17:20:44709def _CheckNoDEPSGIT(input_api, output_api):
710 """Make sure .DEPS.git is never modified manually."""
711 if any(f.LocalPath().endswith('.DEPS.git') for f in
712 input_api.AffectedFiles()):
713 return [output_api.PresubmitError(
714 'Never commit changes to .DEPS.git. This file is maintained by an\n'
715 'automated system based on what\'s in DEPS and your changes will be\n'
716 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34717 '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:44718 'for more information')]
719 return []
720
721
tandriief664692014-09-23 14:51:47722def _CheckValidHostsInDEPS(input_api, output_api):
723 """Checks that DEPS file deps are from allowed_hosts."""
724 # Run only if DEPS file has been modified to annoy fewer bystanders.
725 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
726 return []
727 # Outsource work to gclient verify
728 try:
729 input_api.subprocess.check_output(['gclient', 'verify'])
730 return []
731 except input_api.subprocess.CalledProcessError, error:
732 return [output_api.PresubmitError(
733 'DEPS file must have only git dependencies.',
734 long_text=error.output)]
735
736
[email protected]127f18ec2012-06-16 05:05:59737def _CheckNoBannedFunctions(input_api, output_api):
738 """Make sure that banned functions are not used."""
739 warnings = []
740 errors = []
741
wnwenbdc444e2016-05-25 13:44:15742 def IsBlacklisted(affected_file, blacklist):
743 local_path = affected_file.LocalPath()
744 for item in blacklist:
745 if input_api.re.match(item, local_path):
746 return True
747 return False
748
749 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
750 matched = False
751 if func_name[0:1] == '/':
752 regex = func_name[1:]
753 if input_api.re.search(regex, line):
754 matched = True
755 elif func_name in line:
dchenge07de812016-06-20 19:27:17756 matched = True
wnwenbdc444e2016-05-25 13:44:15757 if matched:
dchenge07de812016-06-20 19:27:17758 problems = warnings
wnwenbdc444e2016-05-25 13:44:15759 if error:
dchenge07de812016-06-20 19:27:17760 problems = errors
wnwenbdc444e2016-05-25 13:44:15761 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
762 for message_line in message:
763 problems.append(' %s' % message_line)
764
Eric Stevensona9a980972017-09-23 00:04:41765 file_filter = lambda f: f.LocalPath().endswith(('.java'))
766 for f in input_api.AffectedFiles(file_filter=file_filter):
767 for line_num, line in f.ChangedContents():
768 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
769 CheckForMatch(f, line_num, line, func_name, message, error)
770
[email protected]127f18ec2012-06-16 05:05:59771 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
772 for f in input_api.AffectedFiles(file_filter=file_filter):
773 for line_num, line in f.ChangedContents():
774 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15775 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59776
777 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
778 for f in input_api.AffectedFiles(file_filter=file_filter):
779 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49780 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49781 if IsBlacklisted(f, excluded_paths):
782 continue
wnwenbdc444e2016-05-25 13:44:15783 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59784
785 result = []
786 if (warnings):
787 result.append(output_api.PresubmitPromptWarning(
788 'Banned functions were used.\n' + '\n'.join(warnings)))
789 if (errors):
790 result.append(output_api.PresubmitError(
791 'Banned functions were used.\n' + '\n'.join(errors)))
792 return result
793
794
[email protected]6c063c62012-07-11 19:11:06795def _CheckNoPragmaOnce(input_api, output_api):
796 """Make sure that banned functions are not used."""
797 files = []
798 pattern = input_api.re.compile(r'^#pragma\s+once',
799 input_api.re.MULTILINE)
800 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
801 if not f.LocalPath().endswith('.h'):
802 continue
803 contents = input_api.ReadFile(f)
804 if pattern.search(contents):
805 files.append(f)
806
807 if files:
808 return [output_api.PresubmitError(
809 'Do not use #pragma once in header files.\n'
810 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
811 files)]
812 return []
813
[email protected]127f18ec2012-06-16 05:05:59814
[email protected]e7479052012-09-19 00:26:12815def _CheckNoTrinaryTrueFalse(input_api, output_api):
816 """Checks to make sure we don't introduce use of foo ? true : false."""
817 problems = []
818 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
819 for f in input_api.AffectedFiles():
820 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
821 continue
822
823 for line_num, line in f.ChangedContents():
824 if pattern.match(line):
825 problems.append(' %s:%d' % (f.LocalPath(), line_num))
826
827 if not problems:
828 return []
829 return [output_api.PresubmitPromptWarning(
830 'Please consider avoiding the "? true : false" pattern if possible.\n' +
831 '\n'.join(problems))]
832
833
[email protected]55f9f382012-07-31 11:02:18834def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28835 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18836 change. Breaking - rules is an error, breaking ! rules is a
837 warning.
838 """
mohan.reddyf21db962014-10-16 12:26:47839 import sys
[email protected]55f9f382012-07-31 11:02:18840 # We need to wait until we have an input_api object and use this
841 # roundabout construct to import checkdeps because this file is
842 # eval-ed and thus doesn't have __file__.
843 original_sys_path = sys.path
844 try:
845 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47846 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18847 import checkdeps
848 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:24849 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:28850 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18851 from rules import Rule
852 finally:
853 # Restore sys.path to what it was before.
854 sys.path = original_sys_path
855
856 added_includes = []
rhalavati08acd232017-04-03 07:23:28857 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:24858 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:18859 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28860 if CppChecker.IsCppFile(f.LocalPath()):
861 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08862 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:28863 elif ProtoChecker.IsProtoFile(f.LocalPath()):
864 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08865 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:24866 elif JavaChecker.IsJavaFile(f.LocalPath()):
867 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08868 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18869
[email protected]26385172013-05-09 23:11:35870 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18871
872 error_descriptions = []
873 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28874 error_subjects = set()
875 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18876 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
877 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:08878 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18879 description_with_path = '%s\n %s' % (path, rule_description)
880 if rule_type == Rule.DISALLOW:
881 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28882 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18883 else:
884 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28885 warning_subjects.add("#includes")
886
887 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
888 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:08889 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:28890 description_with_path = '%s\n %s' % (path, rule_description)
891 if rule_type == Rule.DISALLOW:
892 error_descriptions.append(description_with_path)
893 error_subjects.add("imports")
894 else:
895 warning_descriptions.append(description_with_path)
896 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18897
Jinsuk Kim5a092672017-10-24 22:42:24898 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:02899 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:08900 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:24901 description_with_path = '%s\n %s' % (path, rule_description)
902 if rule_type == Rule.DISALLOW:
903 error_descriptions.append(description_with_path)
904 error_subjects.add("imports")
905 else:
906 warning_descriptions.append(description_with_path)
907 warning_subjects.add("imports")
908
[email protected]55f9f382012-07-31 11:02:18909 results = []
910 if error_descriptions:
911 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28912 'You added one or more %s that violate checkdeps rules.'
913 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18914 error_descriptions))
915 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42916 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28917 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18918 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28919 '%s? See relevant DEPS file(s) for details and contacts.' %
920 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18921 warning_descriptions))
922 return results
923
924
[email protected]fbcafe5a2012-08-08 15:31:22925def _CheckFilePermissions(input_api, output_api):
926 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15927 if input_api.platform == 'win32':
928 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29929 checkperms_tool = input_api.os_path.join(
930 input_api.PresubmitLocalPath(),
931 'tools', 'checkperms', 'checkperms.py')
932 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47933 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:39934 with input_api.CreateTemporaryFile() as file_list:
935 for f in input_api.AffectedFiles():
936 # checkperms.py file/directory arguments must be relative to the
937 # repository.
938 file_list.write(f.LocalPath() + '\n')
939 file_list.close()
940 args += ['--file-list', file_list.name]
941 try:
942 input_api.subprocess.check_output(args)
943 return []
944 except input_api.subprocess.CalledProcessError as error:
945 return [output_api.PresubmitError(
946 'checkperms.py failed:',
947 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22948
949
robertocn832f5992017-01-04 19:01:30950def _CheckTeamTags(input_api, output_api):
951 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
952 checkteamtags_tool = input_api.os_path.join(
953 input_api.PresubmitLocalPath(),
954 'tools', 'checkteamtags', 'checkteamtags.py')
955 args = [input_api.python_executable, checkteamtags_tool,
956 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22957 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30958 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
959 'OWNERS']
960 try:
961 if files:
962 input_api.subprocess.check_output(args + files)
963 return []
964 except input_api.subprocess.CalledProcessError as error:
965 return [output_api.PresubmitError(
966 'checkteamtags.py failed:',
967 long_text=error.output)]
968
969
[email protected]c8278b32012-10-30 20:35:49970def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
971 """Makes sure we don't include ui/aura/window_property.h
972 in header files.
973 """
974 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
975 errors = []
976 for f in input_api.AffectedFiles():
977 if not f.LocalPath().endswith('.h'):
978 continue
979 for line_num, line in f.ChangedContents():
980 if pattern.match(line):
981 errors.append(' %s:%d' % (f.LocalPath(), line_num))
982
983 results = []
984 if errors:
985 results.append(output_api.PresubmitError(
986 'Header files should not include ui/aura/window_property.h', errors))
987 return results
988
989
[email protected]70ca77752012-11-20 03:45:03990def _CheckForVersionControlConflictsInFile(input_api, f):
991 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
992 errors = []
993 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23994 if f.LocalPath().endswith('.md'):
995 # First-level headers in markdown look a lot like version control
996 # conflict markers. http://daringfireball.net/projects/markdown/basics
997 continue
[email protected]70ca77752012-11-20 03:45:03998 if pattern.match(line):
999 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1000 return errors
1001
1002
1003def _CheckForVersionControlConflicts(input_api, output_api):
1004 """Usually this is not intentional and will cause a compile failure."""
1005 errors = []
1006 for f in input_api.AffectedFiles():
1007 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1008
1009 results = []
1010 if errors:
1011 results.append(output_api.PresubmitError(
1012 'Version control conflict markers found, please resolve.', errors))
1013 return results
1014
estadee17314a02017-01-12 16:22:161015def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1016 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1017 errors = []
1018 for f in input_api.AffectedFiles():
1019 for line_num, line in f.ChangedContents():
1020 if pattern.search(line):
1021 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1022
1023 results = []
1024 if errors:
1025 results.append(output_api.PresubmitPromptWarning(
1026 'Found Google support URL addressed by answer number. Please replace with '
1027 'a p= identifier instead. See crbug.com/679462\n', errors))
1028 return results
1029
[email protected]70ca77752012-11-20 03:45:031030
[email protected]06e6d0ff2012-12-11 01:36:441031def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1032 def FilterFile(affected_file):
1033 """Filter function for use with input_api.AffectedSourceFiles,
1034 below. This filters out everything except non-test files from
1035 top-level directories that generally speaking should not hard-code
1036 service URLs (e.g. src/android_webview/, src/content/ and others).
1037 """
1038 return input_api.FilterSourceFile(
1039 affected_file,
[email protected]78bb39d62012-12-11 15:11:561040 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441041 black_list=(_EXCLUDED_PATHS +
1042 _TEST_CODE_EXCLUDED_PATHS +
1043 input_api.DEFAULT_BLACK_LIST))
1044
reillyi38965732015-11-16 18:27:331045 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1046 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461047 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1048 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441049 problems = [] # items are (filename, line_number, line)
1050 for f in input_api.AffectedSourceFiles(FilterFile):
1051 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461052 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441053 problems.append((f.LocalPath(), line_num, line))
1054
1055 if problems:
[email protected]f7051d52013-04-02 18:31:421056 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441057 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581058 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441059 [' %s:%d: %s' % (
1060 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031061 else:
1062 return []
[email protected]06e6d0ff2012-12-11 01:36:441063
1064
[email protected]d2530012013-01-25 16:39:271065def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1066 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311067 The native_client_sdk directory is excluded because it has auto-generated PNG
1068 files for documentation.
[email protected]d2530012013-01-25 16:39:271069 """
[email protected]d2530012013-01-25 16:39:271070 errors = []
binji0dcdf342014-12-12 18:32:311071 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1072 black_list = (r'^native_client_sdk[\\\/]',)
1073 file_filter = lambda f: input_api.FilterSourceFile(
1074 f, white_list=white_list, black_list=black_list)
1075 for f in input_api.AffectedFiles(include_deletes=False,
1076 file_filter=file_filter):
1077 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271078
1079 results = []
1080 if errors:
1081 results.append(output_api.PresubmitError(
1082 'The name of PNG files should not have abbreviations. \n'
1083 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1084 'Contact [email protected] if you have questions.', errors))
1085 return results
1086
1087
Daniel Cheng4dcdb6b2017-04-13 08:30:171088def _ExtractAddRulesFromParsedDeps(parsed_deps):
1089 """Extract the rules that add dependencies from a parsed DEPS file.
1090
1091 Args:
1092 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1093 add_rules = set()
1094 add_rules.update([
1095 rule[1:] for rule in parsed_deps.get('include_rules', [])
1096 if rule.startswith('+') or rule.startswith('!')
1097 ])
1098 for specific_file, rules in parsed_deps.get('specific_include_rules',
1099 {}).iteritems():
1100 add_rules.update([
1101 rule[1:] for rule in rules
1102 if rule.startswith('+') or rule.startswith('!')
1103 ])
1104 return add_rules
1105
1106
1107def _ParseDeps(contents):
1108 """Simple helper for parsing DEPS files."""
1109 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171110 class _VarImpl:
1111
1112 def __init__(self, local_scope):
1113 self._local_scope = local_scope
1114
1115 def Lookup(self, var_name):
1116 """Implements the Var syntax."""
1117 try:
1118 return self._local_scope['vars'][var_name]
1119 except KeyError:
1120 raise Exception('Var is not defined: %s' % var_name)
1121
1122 local_scope = {}
1123 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171124 'Var': _VarImpl(local_scope).Lookup,
1125 }
1126 exec contents in global_scope, local_scope
1127 return local_scope
1128
1129
1130def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081131 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411132 a set of DEPS entries that we should look up.
1133
1134 For a directory (rather than a specific filename) we fake a path to
1135 a specific filename by adding /DEPS. This is chosen as a file that
1136 will seldom or never be subject to per-file include_rules.
1137 """
[email protected]2b438d62013-11-14 17:54:141138 # We ignore deps entries on auto-generated directories.
1139 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081140
Daniel Cheng4dcdb6b2017-04-13 08:30:171141 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1142 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1143
1144 added_deps = new_deps.difference(old_deps)
1145
[email protected]2b438d62013-11-14 17:54:141146 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171147 for added_dep in added_deps:
1148 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1149 continue
1150 # Assume that a rule that ends in .h is a rule for a specific file.
1151 if added_dep.endswith('.h'):
1152 results.add(added_dep)
1153 else:
1154 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081155 return results
1156
1157
[email protected]e871964c2013-05-13 14:14:551158def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1159 """When a dependency prefixed with + is added to a DEPS file, we
1160 want to make sure that the change is reviewed by an OWNER of the
1161 target file or directory, to avoid layering violations from being
1162 introduced. This check verifies that this happens.
1163 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171164 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241165
1166 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191167 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241168 for f in input_api.AffectedFiles(include_deletes=False,
1169 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551170 filename = input_api.os_path.basename(f.LocalPath())
1171 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171172 virtual_depended_on_files.update(_CalculateAddedDeps(
1173 input_api.os_path,
1174 '\n'.join(f.OldContents()),
1175 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551176
[email protected]e871964c2013-05-13 14:14:551177 if not virtual_depended_on_files:
1178 return []
1179
1180 if input_api.is_committing:
1181 if input_api.tbr:
1182 return [output_api.PresubmitNotifyResult(
1183 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271184 if input_api.dry_run:
1185 return [output_api.PresubmitNotifyResult(
1186 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551187 if not input_api.change.issue:
1188 return [output_api.PresubmitError(
1189 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401190 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551191 output = output_api.PresubmitError
1192 else:
1193 output = output_api.PresubmitNotifyResult
1194
1195 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501196 owner_email, reviewers = (
1197 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1198 input_api,
1199 owners_db.email_regexp,
1200 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551201
1202 owner_email = owner_email or input_api.change.author_email
1203
[email protected]de4f7d22013-05-23 14:27:461204 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511205 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461206 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551207 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1208 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411209
1210 # We strip the /DEPS part that was added by
1211 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1212 # directory.
1213 def StripDeps(path):
1214 start_deps = path.rfind('/DEPS')
1215 if start_deps != -1:
1216 return path[:start_deps]
1217 else:
1218 return path
1219 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551220 for path in missing_files]
1221
1222 if unapproved_dependencies:
1223 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151224 output('You need LGTM from owners of depends-on paths in DEPS that were '
1225 'modified in this CL:\n %s' %
1226 '\n '.join(sorted(unapproved_dependencies)))]
1227 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1228 output_list.append(output(
1229 'Suggested missing target path OWNERS:\n %s' %
1230 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551231 return output_list
1232
1233 return []
1234
1235
[email protected]85218562013-11-22 07:41:401236def _CheckSpamLogging(input_api, output_api):
1237 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1238 black_list = (_EXCLUDED_PATHS +
1239 _TEST_CODE_EXCLUDED_PATHS +
1240 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501241 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191242 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481243 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461244 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121245 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1246 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581247 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591248 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161249 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031250 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151251 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1252 r"^chromecast[\\\/]",
1253 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481254 r"^components[\\\/]browser_watcher[\\\/]"
1255 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311256 r"^components[\\\/]html_viewer[\\\/]"
1257 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461258 # TODO(peter): Remove this exception. https://crbug.com/534537
1259 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1260 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251261 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1262 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241263 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111264 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151265 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111266 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521267 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501268 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361269 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311270 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131271 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001272 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441273 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451274 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021275 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351276 r"dump_file_system.cc$",
1277 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401278 source_file_filter = lambda x: input_api.FilterSourceFile(
1279 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1280
thomasanderson625d3932017-03-29 07:16:581281 log_info = set([])
1282 printf = set([])
[email protected]85218562013-11-22 07:41:401283
1284 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581285 for _, line in f.ChangedContents():
1286 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1287 log_info.add(f.LocalPath())
1288 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1289 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371290
thomasanderson625d3932017-03-29 07:16:581291 if input_api.re.search(r"\bprintf\(", line):
1292 printf.add(f.LocalPath())
1293 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1294 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401295
1296 if log_info:
1297 return [output_api.PresubmitError(
1298 'These files spam the console log with LOG(INFO):',
1299 items=log_info)]
1300 if printf:
1301 return [output_api.PresubmitError(
1302 'These files spam the console log with printf/fprintf:',
1303 items=printf)]
1304 return []
1305
1306
[email protected]49aa76a2013-12-04 06:59:161307def _CheckForAnonymousVariables(input_api, output_api):
1308 """These types are all expected to hold locks while in scope and
1309 so should never be anonymous (which causes them to be immediately
1310 destroyed)."""
1311 they_who_must_be_named = [
1312 'base::AutoLock',
1313 'base::AutoReset',
1314 'base::AutoUnlock',
1315 'SkAutoAlphaRestore',
1316 'SkAutoBitmapShaderInstall',
1317 'SkAutoBlitterChoose',
1318 'SkAutoBounderCommit',
1319 'SkAutoCallProc',
1320 'SkAutoCanvasRestore',
1321 'SkAutoCommentBlock',
1322 'SkAutoDescriptor',
1323 'SkAutoDisableDirectionCheck',
1324 'SkAutoDisableOvalCheck',
1325 'SkAutoFree',
1326 'SkAutoGlyphCache',
1327 'SkAutoHDC',
1328 'SkAutoLockColors',
1329 'SkAutoLockPixels',
1330 'SkAutoMalloc',
1331 'SkAutoMaskFreeImage',
1332 'SkAutoMutexAcquire',
1333 'SkAutoPathBoundsUpdate',
1334 'SkAutoPDFRelease',
1335 'SkAutoRasterClipValidate',
1336 'SkAutoRef',
1337 'SkAutoTime',
1338 'SkAutoTrace',
1339 'SkAutoUnref',
1340 ]
1341 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1342 # bad: base::AutoLock(lock.get());
1343 # not bad: base::AutoLock lock(lock.get());
1344 bad_pattern = input_api.re.compile(anonymous)
1345 # good: new base::AutoLock(lock.get())
1346 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1347 errors = []
1348
1349 for f in input_api.AffectedFiles():
1350 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1351 continue
1352 for linenum, line in f.ChangedContents():
1353 if bad_pattern.search(line) and not good_pattern.search(line):
1354 errors.append('%s:%d' % (f.LocalPath(), linenum))
1355
1356 if errors:
1357 return [output_api.PresubmitError(
1358 'These lines create anonymous variables that need to be named:',
1359 items=errors)]
1360 return []
1361
1362
[email protected]999261d2014-03-03 20:08:081363def _CheckUserActionUpdate(input_api, output_api):
1364 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521365 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081366 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521367 # If actions.xml is already included in the changelist, the PRESUBMIT
1368 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081369 return []
1370
[email protected]999261d2014-03-03 20:08:081371 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1372 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521373 current_actions = None
[email protected]999261d2014-03-03 20:08:081374 for f in input_api.AffectedFiles(file_filter=file_filter):
1375 for line_num, line in f.ChangedContents():
1376 match = input_api.re.search(action_re, line)
1377 if match:
[email protected]2f92dec2014-03-07 19:21:521378 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1379 # loaded only once.
1380 if not current_actions:
1381 with open('tools/metrics/actions/actions.xml') as actions_f:
1382 current_actions = actions_f.read()
1383 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081384 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521385 action = 'name="{0}"'.format(action_name)
1386 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081387 return [output_api.PresubmitPromptWarning(
1388 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521389 'tools/metrics/actions/actions.xml. Please run '
1390 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081391 % (f.LocalPath(), line_num, action_name))]
1392 return []
1393
1394
Daniel Cheng13ca61a882017-08-25 15:11:251395def _ImportJSONCommentEater(input_api):
1396 import sys
1397 sys.path = sys.path + [input_api.os_path.join(
1398 input_api.PresubmitLocalPath(),
1399 'tools', 'json_comment_eater')]
1400 import json_comment_eater
1401 return json_comment_eater
1402
1403
[email protected]99171a92014-06-03 08:44:471404def _GetJSONParseError(input_api, filename, eat_comments=True):
1405 try:
1406 contents = input_api.ReadFile(filename)
1407 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251408 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131409 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471410
1411 input_api.json.loads(contents)
1412 except ValueError as e:
1413 return e
1414 return None
1415
1416
1417def _GetIDLParseError(input_api, filename):
1418 try:
1419 contents = input_api.ReadFile(filename)
1420 idl_schema = input_api.os_path.join(
1421 input_api.PresubmitLocalPath(),
1422 'tools', 'json_schema_compiler', 'idl_schema.py')
1423 process = input_api.subprocess.Popen(
1424 [input_api.python_executable, idl_schema],
1425 stdin=input_api.subprocess.PIPE,
1426 stdout=input_api.subprocess.PIPE,
1427 stderr=input_api.subprocess.PIPE,
1428 universal_newlines=True)
1429 (_, error) = process.communicate(input=contents)
1430 return error or None
1431 except ValueError as e:
1432 return e
1433
1434
1435def _CheckParseErrors(input_api, output_api):
1436 """Check that IDL and JSON files do not contain syntax errors."""
1437 actions = {
1438 '.idl': _GetIDLParseError,
1439 '.json': _GetJSONParseError,
1440 }
[email protected]99171a92014-06-03 08:44:471441 # Most JSON files are preprocessed and support comments, but these do not.
1442 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491443 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471444 ]
1445 # Only run IDL checker on files in these directories.
1446 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491447 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1448 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471449 ]
1450
1451 def get_action(affected_file):
1452 filename = affected_file.LocalPath()
1453 return actions.get(input_api.os_path.splitext(filename)[1])
1454
[email protected]99171a92014-06-03 08:44:471455 def FilterFile(affected_file):
1456 action = get_action(affected_file)
1457 if not action:
1458 return False
1459 path = affected_file.LocalPath()
1460
Sean Kau46e29bc2017-08-28 16:31:161461 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471462 return False
1463
1464 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161465 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471466 return False
1467 return True
1468
1469 results = []
1470 for affected_file in input_api.AffectedFiles(
1471 file_filter=FilterFile, include_deletes=False):
1472 action = get_action(affected_file)
1473 kwargs = {}
1474 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161475 _MatchesFile(input_api, json_no_comments_patterns,
1476 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471477 kwargs['eat_comments'] = False
1478 parse_error = action(input_api,
1479 affected_file.AbsoluteLocalPath(),
1480 **kwargs)
1481 if parse_error:
1482 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1483 (affected_file.LocalPath(), parse_error)))
1484 return results
1485
1486
[email protected]760deea2013-12-10 19:33:491487def _CheckJavaStyle(input_api, output_api):
1488 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471489 import sys
[email protected]760deea2013-12-10 19:33:491490 original_sys_path = sys.path
1491 try:
1492 sys.path = sys.path + [input_api.os_path.join(
1493 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1494 import checkstyle
1495 finally:
1496 # Restore sys.path to what it was before.
1497 sys.path = original_sys_path
1498
1499 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091500 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511501 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491502
1503
Sean Kau46e29bc2017-08-28 16:31:161504def _MatchesFile(input_api, patterns, path):
1505 for pattern in patterns:
1506 if input_api.re.search(pattern, path):
1507 return True
1508 return False
1509
1510
Daniel Cheng7052cdf2017-11-21 19:23:291511def _GetOwnersFilesToCheckForIpcOwners(input_api):
1512 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:171513
Daniel Cheng7052cdf2017-11-21 19:23:291514 Returns:
1515 A dictionary mapping an OWNER file to the list of OWNERS rules it must
1516 contain to cover IPC-related files with noparent reviewer rules.
1517 """
1518 # Whether or not a file affects IPC is (mostly) determined by a simple list
1519 # of filename patterns.
dchenge07de812016-06-20 19:27:171520 file_patterns = [
palmerb19a0932017-01-24 04:00:311521 # Legacy IPC:
dchenge07de812016-06-20 19:27:171522 '*_messages.cc',
1523 '*_messages*.h',
1524 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311525 # Mojo IPC:
dchenge07de812016-06-20 19:27:171526 '*.mojom',
1527 '*_struct_traits*.*',
1528 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311529 '*.typemap',
1530 # Android native IPC:
1531 '*.aidl',
1532 # Blink uses a different file naming convention:
1533 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171534 '*StructTraits*.*',
1535 '*TypeConverter*.*',
1536 ]
1537
scottmg7a6ed5ba2016-11-04 18:22:041538 # These third_party directories do not contain IPCs, but contain files
1539 # matching the above patterns, which trigger false positives.
1540 exclude_paths = [
1541 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291542 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041543 ]
1544
dchenge07de812016-06-20 19:27:171545 # Dictionary mapping an OWNERS file path to Patterns.
1546 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1547 # rules ) to a PatternEntry.
1548 # PatternEntry is a dictionary with two keys:
1549 # - 'files': the files that are matched by this pattern
1550 # - 'rules': the per-file rules needed for this pattern
1551 # For example, if we expect OWNERS file to contain rules for *.mojom and
1552 # *_struct_traits*.*, Patterns might look like this:
1553 # {
1554 # '*.mojom': {
1555 # 'files': ...,
1556 # 'rules': [
1557 # 'per-file *.mojom=set noparent',
1558 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1559 # ],
1560 # },
1561 # '*_struct_traits*.*': {
1562 # 'files': ...,
1563 # 'rules': [
1564 # 'per-file *_struct_traits*.*=set noparent',
1565 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1566 # ],
1567 # },
1568 # }
1569 to_check = {}
1570
Daniel Cheng13ca61a882017-08-25 15:11:251571 def AddPatternToCheck(input_file, pattern):
1572 owners_file = input_api.os_path.join(
1573 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1574 if owners_file not in to_check:
1575 to_check[owners_file] = {}
1576 if pattern not in to_check[owners_file]:
1577 to_check[owners_file][pattern] = {
1578 'files': [],
1579 'rules': [
1580 'per-file %s=set noparent' % pattern,
1581 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1582 ]
1583 }
1584 to_check[owners_file][pattern]['files'].append(f)
1585
dchenge07de812016-06-20 19:27:171586 # Iterate through the affected files to see what we actually need to check
1587 # for. We should only nag patch authors about per-file rules if a file in that
1588 # directory would match that pattern. If a directory only contains *.mojom
1589 # files and no *_messages*.h files, we should only nag about rules for
1590 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251591 for f in input_api.AffectedFiles(include_deletes=False):
1592 # Manifest files don't have a strong naming convention. Instead, scan
1593 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161594 if (f.LocalPath().endswith('.json') and
1595 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1596 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251597 json_comment_eater = _ImportJSONCommentEater(input_api)
1598 mostly_json_lines = '\n'.join(f.NewContents())
1599 # Comments aren't allowed in strict JSON, so filter them out.
1600 json_lines = json_comment_eater.Nom(mostly_json_lines)
1601 json_content = input_api.json.loads(json_lines)
1602 if 'interface_provider_specs' in json_content:
1603 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171604 for pattern in file_patterns:
1605 if input_api.fnmatch.fnmatch(
1606 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041607 skip = False
1608 for exclude in exclude_paths:
1609 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1610 skip = True
1611 break
1612 if skip:
1613 continue
Daniel Cheng13ca61a882017-08-25 15:11:251614 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171615 break
1616
Daniel Cheng7052cdf2017-11-21 19:23:291617 return to_check
1618
1619
1620def _CheckIpcOwners(input_api, output_api):
1621 """Checks that affected files involving IPC have an IPC OWNERS rule."""
1622 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
1623
1624 if to_check:
1625 # If there are any OWNERS files to check, there are IPC-related changes in
1626 # this CL. Auto-CC the review list.
1627 output_api.AppendCC('[email protected]')
1628
1629 # Go through the OWNERS files to check, filtering out rules that are already
1630 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:171631 for owners_file, patterns in to_check.iteritems():
1632 try:
1633 with file(owners_file) as f:
1634 lines = set(f.read().splitlines())
1635 for entry in patterns.itervalues():
1636 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1637 ]
1638 except IOError:
1639 # No OWNERS file, so all the rules are definitely missing.
1640 continue
1641
1642 # All the remaining lines weren't found in OWNERS files, so emit an error.
1643 errors = []
1644 for owners_file, patterns in to_check.iteritems():
1645 missing_lines = []
1646 files = []
1647 for pattern, entry in patterns.iteritems():
1648 missing_lines.extend(entry['rules'])
1649 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1650 if missing_lines:
1651 errors.append(
Daniel Cheng52111692017-06-14 08:00:591652 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171653 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1654
1655 results = []
1656 if errors:
vabrf5ce3bf92016-07-11 14:52:411657 if input_api.is_committing:
1658 output = output_api.PresubmitError
1659 else:
1660 output = output_api.PresubmitPromptWarning
1661 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591662 'Found OWNERS files that need to be updated for IPC security ' +
1663 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171664 long_text='\n\n'.join(errors)))
1665
1666 return results
1667
1668
jbriance9e12f162016-11-25 07:57:501669def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311670 """Checks that added or removed lines in non third party affected
1671 header files do not lead to new useless class or struct forward
1672 declaration.
jbriance9e12f162016-11-25 07:57:501673 """
1674 results = []
1675 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1676 input_api.re.MULTILINE)
1677 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1678 input_api.re.MULTILINE)
1679 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311680 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191681 not f.LocalPath().startswith('third_party/blink') and
1682 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311683 not f.LocalPath().startswith('third_party/WebKit') and
1684 not f.LocalPath().startswith('third_party\\WebKit')):
1685 continue
1686
jbriance9e12f162016-11-25 07:57:501687 if not f.LocalPath().endswith('.h'):
1688 continue
1689
1690 contents = input_api.ReadFile(f)
1691 fwd_decls = input_api.re.findall(class_pattern, contents)
1692 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1693
1694 useless_fwd_decls = []
1695 for decl in fwd_decls:
1696 count = sum(1 for _ in input_api.re.finditer(
1697 r'\b%s\b' % input_api.re.escape(decl), contents))
1698 if count == 1:
1699 useless_fwd_decls.append(decl)
1700
1701 if not useless_fwd_decls:
1702 continue
1703
1704 for line in f.GenerateScmDiff().splitlines():
1705 if (line.startswith('-') and not line.startswith('--') or
1706 line.startswith('+') and not line.startswith('++')):
1707 for decl in useless_fwd_decls:
1708 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1709 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241710 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501711 (f.LocalPath(), decl)))
1712 useless_fwd_decls.remove(decl)
1713
1714 return results
1715
1716
dskiba88634f4e2015-08-14 23:03:291717def _CheckAndroidToastUsage(input_api, output_api):
1718 """Checks that code uses org.chromium.ui.widget.Toast instead of
1719 android.widget.Toast (Chromium Toast doesn't force hardware
1720 acceleration on low-end devices, saving memory).
1721 """
1722 toast_import_pattern = input_api.re.compile(
1723 r'^import android\.widget\.Toast;$')
1724
1725 errors = []
1726
1727 sources = lambda affected_file: input_api.FilterSourceFile(
1728 affected_file,
1729 black_list=(_EXCLUDED_PATHS +
1730 _TEST_CODE_EXCLUDED_PATHS +
1731 input_api.DEFAULT_BLACK_LIST +
1732 (r'^chromecast[\\\/].*',
1733 r'^remoting[\\\/].*')),
1734 white_list=(r'.*\.java$',))
1735
1736 for f in input_api.AffectedSourceFiles(sources):
1737 for line_num, line in f.ChangedContents():
1738 if toast_import_pattern.search(line):
1739 errors.append("%s:%d" % (f.LocalPath(), line_num))
1740
1741 results = []
1742
1743 if errors:
1744 results.append(output_api.PresubmitError(
1745 'android.widget.Toast usage is detected. Android toasts use hardware'
1746 ' acceleration, and can be\ncostly on low-end devices. Please use'
1747 ' org.chromium.ui.widget.Toast instead.\n'
1748 'Contact [email protected] if you have any questions.',
1749 errors))
1750
1751 return results
1752
1753
dgnaa68d5e2015-06-10 10:08:221754def _CheckAndroidCrLogUsage(input_api, output_api):
1755 """Checks that new logs using org.chromium.base.Log:
1756 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511757 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221758 """
pkotwicza1dd0b002016-05-16 14:41:041759
torne89540622017-03-24 19:41:301760 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041761 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301762 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041763 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301764 # WebView license viewer code cannot depend on //base; used in stub APK.
1765 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1766 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041767 ]
1768
dgnaa68d5e2015-06-10 10:08:221769 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121770 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1771 class_in_base_pattern = input_api.re.compile(
1772 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1773 has_some_log_import_pattern = input_api.re.compile(
1774 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221775 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121776 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221777 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511778 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221779 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221780
Vincent Scheib16d7b272015-09-15 18:09:071781 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221782 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041783 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1784 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121785
dgnaa68d5e2015-06-10 10:08:221786 tag_decl_errors = []
1787 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121788 tag_errors = []
dgn38736db2015-09-18 19:20:511789 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121790 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221791
1792 for f in input_api.AffectedSourceFiles(sources):
1793 file_content = input_api.ReadFile(f)
1794 has_modified_logs = False
1795
1796 # Per line checks
dgn87d9fb62015-06-12 09:15:121797 if (cr_log_import_pattern.search(file_content) or
1798 (class_in_base_pattern.search(file_content) and
1799 not has_some_log_import_pattern.search(file_content))):
1800 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221801 for line_num, line in f.ChangedContents():
1802
1803 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121804 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221805 if match:
1806 has_modified_logs = True
1807
1808 # Make sure it uses "TAG"
1809 if not match.group('tag') == 'TAG':
1810 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121811 else:
1812 # Report non cr Log function calls in changed lines
1813 for line_num, line in f.ChangedContents():
1814 if log_call_pattern.search(line):
1815 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221816
1817 # Per file checks
1818 if has_modified_logs:
1819 # Make sure the tag is using the "cr" prefix and is not too long
1820 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511821 tag_name = match.group('name') if match else None
1822 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221823 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511824 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221825 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511826 elif '.' in tag_name:
1827 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221828
1829 results = []
1830 if tag_decl_errors:
1831 results.append(output_api.PresubmitPromptWarning(
1832 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511833 '"private static final String TAG = "<package tag>".\n'
1834 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221835 tag_decl_errors))
1836
1837 if tag_length_errors:
1838 results.append(output_api.PresubmitError(
1839 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511840 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221841 tag_length_errors))
1842
1843 if tag_errors:
1844 results.append(output_api.PresubmitPromptWarning(
1845 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1846 tag_errors))
1847
dgn87d9fb62015-06-12 09:15:121848 if util_log_errors:
dgn4401aa52015-04-29 16:26:171849 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121850 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1851 util_log_errors))
1852
dgn38736db2015-09-18 19:20:511853 if tag_with_dot_errors:
1854 results.append(output_api.PresubmitPromptWarning(
1855 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1856 tag_with_dot_errors))
1857
dgn4401aa52015-04-29 16:26:171858 return results
1859
1860
Yoland Yanb92fa522017-08-28 17:37:061861def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1862 """Checks that junit.framework.* is no longer used."""
1863 deprecated_junit_framework_pattern = input_api.re.compile(
1864 r'^import junit\.framework\..*;',
1865 input_api.re.MULTILINE)
1866 sources = lambda x: input_api.FilterSourceFile(
1867 x, white_list=(r'.*\.java$',), black_list=None)
1868 errors = []
1869 for f in input_api.AffectedFiles(sources):
1870 for line_num, line in f.ChangedContents():
1871 if deprecated_junit_framework_pattern.search(line):
1872 errors.append("%s:%d" % (f.LocalPath(), line_num))
1873
1874 results = []
1875 if errors:
1876 results.append(output_api.PresubmitError(
1877 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1878 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1879 ' if you have any question.', errors))
1880 return results
1881
1882
1883def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1884 """Checks that if new Java test classes have inheritance.
1885 Either the new test class is JUnit3 test or it is a JUnit4 test class
1886 with a base class, either case is undesirable.
1887 """
1888 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1889
1890 sources = lambda x: input_api.FilterSourceFile(
1891 x, white_list=(r'.*Test\.java$',), black_list=None)
1892 errors = []
1893 for f in input_api.AffectedFiles(sources):
1894 if not f.OldContents():
1895 class_declaration_start_flag = False
1896 for line_num, line in f.ChangedContents():
1897 if class_declaration_pattern.search(line):
1898 class_declaration_start_flag = True
1899 if class_declaration_start_flag and ' extends ' in line:
1900 errors.append('%s:%d' % (f.LocalPath(), line_num))
1901 if '{' in line:
1902 class_declaration_start_flag = False
1903
1904 results = []
1905 if errors:
1906 results.append(output_api.PresubmitPromptWarning(
1907 'The newly created files include Test classes that inherits from base'
1908 ' class. Please do not use inheritance in JUnit4 tests or add new'
1909 ' JUnit3 tests. Contact [email protected] if you have any'
1910 ' questions.', errors))
1911 return results
1912
yolandyan45001472016-12-21 21:12:421913def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1914 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1915 deprecated_annotation_import_pattern = input_api.re.compile(
1916 r'^import android\.test\.suitebuilder\.annotation\..*;',
1917 input_api.re.MULTILINE)
1918 sources = lambda x: input_api.FilterSourceFile(
1919 x, white_list=(r'.*\.java$',), black_list=None)
1920 errors = []
1921 for f in input_api.AffectedFiles(sources):
1922 for line_num, line in f.ChangedContents():
1923 if deprecated_annotation_import_pattern.search(line):
1924 errors.append("%s:%d" % (f.LocalPath(), line_num))
1925
1926 results = []
1927 if errors:
1928 results.append(output_api.PresubmitError(
1929 'Annotations in android.test.suitebuilder.annotation have been'
1930 ' deprecated since API level 24. Please use android.support.test.filters'
1931 ' from //third_party/android_support_test_runner:runner_java instead.'
1932 ' Contact [email protected] if you have any questions.', errors))
1933 return results
1934
1935
agrieve7b6479d82015-10-07 14:24:221936def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1937 """Checks if MDPI assets are placed in a correct directory."""
1938 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1939 ('/res/drawable/' in f.LocalPath() or
1940 '/res/drawable-ldrtl/' in f.LocalPath()))
1941 errors = []
1942 for f in input_api.AffectedFiles(include_deletes=False,
1943 file_filter=file_filter):
1944 errors.append(' %s' % f.LocalPath())
1945
1946 results = []
1947 if errors:
1948 results.append(output_api.PresubmitError(
1949 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1950 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1951 '/res/drawable-ldrtl/.\n'
1952 'Contact [email protected] if you have questions.', errors))
1953 return results
1954
1955
Nate Fischer535972b2017-09-16 01:06:181956def _CheckAndroidWebkitImports(input_api, output_api):
1957 """Checks that code uses org.chromium.base.Callback instead of
1958 android.widget.ValueCallback except in the WebView glue layer.
1959 """
1960 valuecallback_import_pattern = input_api.re.compile(
1961 r'^import android\.webkit\.ValueCallback;$')
1962
1963 errors = []
1964
1965 sources = lambda affected_file: input_api.FilterSourceFile(
1966 affected_file,
1967 black_list=(_EXCLUDED_PATHS +
1968 _TEST_CODE_EXCLUDED_PATHS +
1969 input_api.DEFAULT_BLACK_LIST +
1970 (r'^android_webview[\\\/]glue[\\\/].*',)),
1971 white_list=(r'.*\.java$',))
1972
1973 for f in input_api.AffectedSourceFiles(sources):
1974 for line_num, line in f.ChangedContents():
1975 if valuecallback_import_pattern.search(line):
1976 errors.append("%s:%d" % (f.LocalPath(), line_num))
1977
1978 results = []
1979
1980 if errors:
1981 results.append(output_api.PresubmitError(
1982 'android.webkit.ValueCallback usage is detected outside of the glue'
1983 ' layer. To stay compatible with the support library, android.webkit.*'
1984 ' classes should only be used inside the glue layer and'
1985 ' org.chromium.base.Callback should be used instead.',
1986 errors))
1987
1988 return results
1989
1990
agrievef32bcc72016-04-04 14:57:401991class PydepsChecker(object):
1992 def __init__(self, input_api, pydeps_files):
1993 self._file_cache = {}
1994 self._input_api = input_api
1995 self._pydeps_files = pydeps_files
1996
1997 def _LoadFile(self, path):
1998 """Returns the list of paths within a .pydeps file relative to //."""
1999 if path not in self._file_cache:
2000 with open(path) as f:
2001 self._file_cache[path] = f.read()
2002 return self._file_cache[path]
2003
2004 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
2005 """Returns an interable of paths within the .pydep, relativized to //."""
2006 os_path = self._input_api.os_path
2007 pydeps_dir = os_path.dirname(pydeps_path)
2008 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2009 if not l.startswith('*'))
2010 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2011
2012 def _CreateFilesToPydepsMap(self):
2013 """Returns a map of local_path -> list_of_pydeps."""
2014 ret = {}
2015 for pydep_local_path in self._pydeps_files:
2016 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2017 ret.setdefault(path, []).append(pydep_local_path)
2018 return ret
2019
2020 def ComputeAffectedPydeps(self):
2021 """Returns an iterable of .pydeps files that might need regenerating."""
2022 affected_pydeps = set()
2023 file_to_pydeps_map = None
2024 for f in self._input_api.AffectedFiles(include_deletes=True):
2025 local_path = f.LocalPath()
2026 if local_path == 'DEPS':
2027 return self._pydeps_files
2028 elif local_path.endswith('.pydeps'):
2029 if local_path in self._pydeps_files:
2030 affected_pydeps.add(local_path)
2031 elif local_path.endswith('.py'):
2032 if file_to_pydeps_map is None:
2033 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2034 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2035 return affected_pydeps
2036
2037 def DetermineIfStale(self, pydeps_path):
2038 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412039 import difflib
agrievef32bcc72016-04-04 14:57:402040 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2041 cmd = old_pydeps_data[1][1:].strip()
John Budorickab2fa102017-10-06 16:59:492042 env = {
2043 'PYTHONDONTWRITEBYTECODE': '1'
2044 }
agrievef32bcc72016-04-04 14:57:402045 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorickab2fa102017-10-06 16:59:492046 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412047 old_contents = old_pydeps_data[2:]
2048 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402049 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412050 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402051
2052
2053def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2054 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:002055 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:282056 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
2057 # Mac, so skip it on other platforms.
2058 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002059 return []
agrievef32bcc72016-04-04 14:57:402060 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
2061 is_android = input_api.os_path.exists('third_party/android_tools')
2062 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2063 results = []
2064 # First, check for new / deleted .pydeps.
2065 for f in input_api.AffectedFiles(include_deletes=True):
2066 if f.LocalPath().endswith('.pydeps'):
2067 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2068 results.append(output_api.PresubmitError(
2069 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2070 'remove %s' % f.LocalPath()))
2071 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2072 results.append(output_api.PresubmitError(
2073 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2074 'include %s' % f.LocalPath()))
2075
2076 if results:
2077 return results
2078
2079 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2080
2081 for pydep_path in checker.ComputeAffectedPydeps():
2082 try:
phajdan.jr0d9878552016-11-04 10:49:412083 result = checker.DetermineIfStale(pydep_path)
2084 if result:
2085 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402086 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412087 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2088 'To regenerate, run:\n\n %s' %
2089 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402090 except input_api.subprocess.CalledProcessError as error:
2091 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2092 long_text=error.output)]
2093
2094 return results
2095
2096
glidere61efad2015-02-18 17:39:432097def _CheckSingletonInHeaders(input_api, output_api):
2098 """Checks to make sure no header files have |Singleton<|."""
2099 def FileFilter(affected_file):
2100 # It's ok for base/memory/singleton.h to have |Singleton<|.
2101 black_list = (_EXCLUDED_PATHS +
2102 input_api.DEFAULT_BLACK_LIST +
2103 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2104 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2105
sergeyu34d21222015-09-16 00:11:442106 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432107 files = []
2108 for f in input_api.AffectedSourceFiles(FileFilter):
2109 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2110 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2111 contents = input_api.ReadFile(f)
2112 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242113 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432114 pattern.search(line)):
2115 files.append(f)
2116 break
2117
2118 if files:
yolandyandaabc6d2016-04-18 18:29:392119 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442120 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432121 'Please move them to an appropriate source file so that the ' +
2122 'template gets instantiated in a single compilation unit.',
2123 files) ]
2124 return []
2125
2126
[email protected]fd20b902014-05-09 02:14:532127_DEPRECATED_CSS = [
2128 # Values
2129 ( "-webkit-box", "flex" ),
2130 ( "-webkit-inline-box", "inline-flex" ),
2131 ( "-webkit-flex", "flex" ),
2132 ( "-webkit-inline-flex", "inline-flex" ),
2133 ( "-webkit-min-content", "min-content" ),
2134 ( "-webkit-max-content", "max-content" ),
2135
2136 # Properties
2137 ( "-webkit-background-clip", "background-clip" ),
2138 ( "-webkit-background-origin", "background-origin" ),
2139 ( "-webkit-background-size", "background-size" ),
2140 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442141 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532142
2143 # Functions
2144 ( "-webkit-gradient", "gradient" ),
2145 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2146 ( "-webkit-linear-gradient", "linear-gradient" ),
2147 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2148 ( "-webkit-radial-gradient", "radial-gradient" ),
2149 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2150]
2151
dbeam1ec68ac2016-12-15 05:22:242152def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532153 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252154 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342155 documentation and iOS CSS for dom distiller
2156 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252157 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532158 results = []
dbeam070cfe62014-10-22 06:44:022159 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252160 black_list = (_EXCLUDED_PATHS +
2161 _TEST_CODE_EXCLUDED_PATHS +
2162 input_api.DEFAULT_BLACK_LIST +
2163 (r"^chrome/common/extensions/docs",
2164 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342165 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442166 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252167 r"^native_client_sdk"))
2168 file_filter = lambda f: input_api.FilterSourceFile(
2169 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532170 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2171 for line_num, line in fpath.ChangedContents():
2172 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022173 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532174 results.append(output_api.PresubmitError(
2175 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2176 (fpath.LocalPath(), line_num, deprecated_value, value)))
2177 return results
2178
mohan.reddyf21db962014-10-16 12:26:472179
dbeam070cfe62014-10-22 06:44:022180_DEPRECATED_JS = [
2181 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2182 ( "__defineGetter__", "Object.defineProperty" ),
2183 ( "__defineSetter__", "Object.defineProperty" ),
2184]
2185
dbeam1ec68ac2016-12-15 05:22:242186def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022187 """Make sure that we don't use deprecated JS in Chrome code."""
2188 results = []
2189 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2190 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2191 input_api.DEFAULT_BLACK_LIST)
2192 file_filter = lambda f: input_api.FilterSourceFile(
2193 f, white_list=file_inclusion_pattern, black_list=black_list)
2194 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2195 for lnum, line in fpath.ChangedContents():
2196 for (deprecated, replacement) in _DEPRECATED_JS:
2197 if deprecated in line:
2198 results.append(output_api.PresubmitError(
2199 "%s:%d: Use of deprecated JS %s, use %s instead" %
2200 (fpath.LocalPath(), lnum, deprecated, replacement)))
2201 return results
2202
dpapadd651231d82017-07-21 02:44:472203def _CheckForRiskyJsArrowFunction(line_number, line):
2204 if ' => ' in line:
2205 return "line %d, is using an => (arrow) function\n %s\n" % (
2206 line_number, line)
2207 return ''
2208
2209def _CheckForRiskyJsConstLet(input_api, line_number, line):
2210 if input_api.re.match('^\s*(const|let)\s', line):
2211 return "line %d, is using const/let keyword\n %s\n" % (
2212 line_number, line)
2213 return ''
dbeam070cfe62014-10-22 06:44:022214
dbeam1ec68ac2016-12-15 05:22:242215def _CheckForRiskyJsFeatures(input_api, output_api):
2216 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002217 # 'ui/webui/resources/cr_components are not allowed on ios'
2218 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572219 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002220 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472221 results = []
dbeam1ec68ac2016-12-15 05:22:242222 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472223 arrow_error_lines = []
2224 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242225 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472226 arrow_error_lines += filter(None, [
2227 _CheckForRiskyJsArrowFunction(lnum, line),
2228 ])
dbeam1ec68ac2016-12-15 05:22:242229
dpapadd651231d82017-07-21 02:44:472230 const_let_error_lines += filter(None, [
2231 _CheckForRiskyJsConstLet(input_api, lnum, line),
2232 ])
dbeam1ec68ac2016-12-15 05:22:242233
dpapadd651231d82017-07-21 02:44:472234 if arrow_error_lines:
2235 arrow_error_lines = map(
2236 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2237 results.append(
2238 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2239"""
2240Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242241%s
2242Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2243https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472244""" % f.LocalPath()
2245 ])))
dbeam1ec68ac2016-12-15 05:22:242246
dpapadd651231d82017-07-21 02:44:472247 if const_let_error_lines:
2248 const_let_error_lines = map(
2249 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2250 results.append(
2251 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2252"""
2253Use of const/let keywords detected in:
2254%s
2255Please ensure your code does not run on iOS9 because const/let is not fully
2256supported.
2257https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2258https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2259""" % f.LocalPath()
2260 ])))
2261
2262 return results
dbeam1ec68ac2016-12-15 05:22:242263
rlanday6802cf632017-05-30 17:48:362264def _CheckForRelativeIncludes(input_api, output_api):
2265 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2266 import sys
2267 original_sys_path = sys.path
2268 try:
2269 sys.path = sys.path + [input_api.os_path.join(
2270 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2271 from cpp_checker import CppChecker
2272 finally:
2273 # Restore sys.path to what it was before.
2274 sys.path = original_sys_path
2275
2276 bad_files = {}
2277 for f in input_api.AffectedFiles(include_deletes=False):
2278 if (f.LocalPath().startswith('third_party') and
2279 not f.LocalPath().startswith('third_party/WebKit') and
2280 not f.LocalPath().startswith('third_party\\WebKit')):
2281 continue
2282
2283 if not CppChecker.IsCppFile(f.LocalPath()):
2284 continue
2285
2286 relative_includes = [line for line_num, line in f.ChangedContents()
2287 if "#include" in line and "../" in line]
2288 if not relative_includes:
2289 continue
2290 bad_files[f.LocalPath()] = relative_includes
2291
2292 if not bad_files:
2293 return []
2294
2295 error_descriptions = []
2296 for file_path, bad_lines in bad_files.iteritems():
2297 error_description = file_path
2298 for line in bad_lines:
2299 error_description += '\n ' + line
2300 error_descriptions.append(error_description)
2301
2302 results = []
2303 results.append(output_api.PresubmitError(
2304 'You added one or more relative #include paths (including "../").\n'
2305 'These shouldn\'t be used because they can be used to include headers\n'
2306 'from code that\'s not correctly specified as a dependency in the\n'
2307 'relevant BUILD.gn file(s).',
2308 error_descriptions))
2309
2310 return results
2311
Takeshi Yoshinoe387aa32017-08-02 13:16:132312
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202313def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2314 if not isinstance(key, ast.Str):
2315 return 'Key at line %d must be a string literal' % key.lineno
2316 if not isinstance(value, ast.Dict):
2317 return 'Value at line %d must be a dict' % value.lineno
2318 if len(value.keys) != 1:
2319 return 'Dict at line %d must have single entry' % value.lineno
2320 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2321 return (
2322 'Entry at line %d must have a string literal \'filepath\' as key' %
2323 value.lineno)
2324 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132325
Takeshi Yoshinoe387aa32017-08-02 13:16:132326
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202327def _CheckWatchlistsEntrySyntax(key, value, ast):
2328 if not isinstance(key, ast.Str):
2329 return 'Key at line %d must be a string literal' % key.lineno
2330 if not isinstance(value, ast.List):
2331 return 'Value at line %d must be a list' % value.lineno
2332 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132333
Takeshi Yoshinoe387aa32017-08-02 13:16:132334
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202335def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2336 mismatch_template = (
2337 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2338 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132339
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202340 i = 0
2341 last_key = ''
2342 while True:
2343 if i >= len(wd_dict.keys):
2344 if i >= len(w_dict.keys):
2345 return None
2346 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2347 elif i >= len(w_dict.keys):
2348 return (
2349 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132350
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202351 wd_key = wd_dict.keys[i]
2352 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132353
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202354 result = _CheckWatchlistDefinitionsEntrySyntax(
2355 wd_key, wd_dict.values[i], ast)
2356 if result is not None:
2357 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132358
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202359 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2360 if result is not None:
2361 return 'Bad entry in WATCHLISTS dict: %s' % result
2362
2363 if wd_key.s != w_key.s:
2364 return mismatch_template % (
2365 '%s at line %d' % (wd_key.s, wd_key.lineno),
2366 '%s at line %d' % (w_key.s, w_key.lineno))
2367
2368 if wd_key.s < last_key:
2369 return (
2370 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2371 (wd_key.lineno, w_key.lineno))
2372 last_key = wd_key.s
2373
2374 i = i + 1
2375
2376
2377def _CheckWATCHLISTSSyntax(expression, ast):
2378 if not isinstance(expression, ast.Expression):
2379 return 'WATCHLISTS file must contain a valid expression'
2380 dictionary = expression.body
2381 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2382 return 'WATCHLISTS file must have single dict with exactly two entries'
2383
2384 first_key = dictionary.keys[0]
2385 first_value = dictionary.values[0]
2386 second_key = dictionary.keys[1]
2387 second_value = dictionary.values[1]
2388
2389 if (not isinstance(first_key, ast.Str) or
2390 first_key.s != 'WATCHLIST_DEFINITIONS' or
2391 not isinstance(first_value, ast.Dict)):
2392 return (
2393 'The first entry of the dict in WATCHLISTS file must be '
2394 'WATCHLIST_DEFINITIONS dict')
2395
2396 if (not isinstance(second_key, ast.Str) or
2397 second_key.s != 'WATCHLISTS' or
2398 not isinstance(second_value, ast.Dict)):
2399 return (
2400 'The second entry of the dict in WATCHLISTS file must be '
2401 'WATCHLISTS dict')
2402
2403 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132404
2405
2406def _CheckWATCHLISTS(input_api, output_api):
2407 for f in input_api.AffectedFiles(include_deletes=False):
2408 if f.LocalPath() == 'WATCHLISTS':
2409 contents = input_api.ReadFile(f, 'r')
2410
2411 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202412 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132413 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202414 # Get an AST tree for it and scan the tree for detailed style checking.
2415 expression = input_api.ast.parse(
2416 contents, filename='WATCHLISTS', mode='eval')
2417 except ValueError as e:
2418 return [output_api.PresubmitError(
2419 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2420 except SyntaxError as e:
2421 return [output_api.PresubmitError(
2422 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2423 except TypeError as e:
2424 return [output_api.PresubmitError(
2425 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132426
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202427 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2428 if result is not None:
2429 return [output_api.PresubmitError(result)]
2430 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132431
2432 return []
2433
2434
dgnaa68d5e2015-06-10 10:08:222435def _AndroidSpecificOnUploadChecks(input_api, output_api):
2436 """Groups checks that target android code."""
2437 results = []
dgnaa68d5e2015-06-10 10:08:222438 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222439 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292440 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062441 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2442 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422443 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182444 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222445 return results
2446
2447
[email protected]22c9bd72011-03-27 16:47:392448def _CommonChecks(input_api, output_api):
2449 """Checks common to both upload and commit."""
2450 results = []
2451 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382452 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542453 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582454 results.extend(
2455 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192456 results.extend(
[email protected]760deea2013-12-10 19:33:492457 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542458 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182459 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522460 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222461 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442462 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592463 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062464 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122465 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182466 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222467 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302468 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492469 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032470 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492471 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442472 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272473 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072474 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542475 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442476 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392477 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552478 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042479 results.extend(
2480 input_api.canned_checks.CheckChangeHasNoTabs(
2481 input_api,
2482 output_api,
2483 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402484 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162485 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082486 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242487 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2488 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472489 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042490 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232491 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432492 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402493 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152494 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172495 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502496 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242497 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362498 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132499 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432500 results.extend(input_api.RunTests(
2501 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242502
2503 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2504 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2505 input_api, output_api,
2506 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382507 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392508 return results
[email protected]1f7b4172010-01-28 01:17:342509
[email protected]b337cb5b2011-01-23 21:24:052510
[email protected]b8079ae4a2012-12-05 19:56:492511def _CheckPatchFiles(input_api, output_api):
2512 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2513 if f.LocalPath().endswith(('.orig', '.rej'))]
2514 if problems:
2515 return [output_api.PresubmitError(
2516 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032517 else:
2518 return []
[email protected]b8079ae4a2012-12-05 19:56:492519
2520
Kent Tamura5a8755d2017-06-29 23:37:072521def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212522 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2523 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2524 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072525 include_re = input_api.re.compile(
2526 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2527 extension_re = input_api.re.compile(r'\.[a-z]+$')
2528 errors = []
2529 for f in input_api.AffectedFiles():
2530 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2531 continue
2532 found_line_number = None
2533 found_macro = None
2534 for line_num, line in f.ChangedContents():
2535 match = macro_re.search(line)
2536 if match:
2537 found_line_number = line_num
2538 found_macro = match.group(2)
2539 break
2540 if not found_line_number:
2541 continue
2542
2543 found_include = False
2544 for line in f.NewContents():
2545 if include_re.search(line):
2546 found_include = True
2547 break
2548 if found_include:
2549 continue
2550
2551 if not f.LocalPath().endswith('.h'):
2552 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2553 try:
2554 content = input_api.ReadFile(primary_header_path, 'r')
2555 if include_re.search(content):
2556 continue
2557 except IOError:
2558 pass
2559 errors.append('%s:%d %s macro is used without including build/'
2560 'build_config.h.'
2561 % (f.LocalPath(), found_line_number, found_macro))
2562 if errors:
2563 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2564 return []
2565
2566
[email protected]b00342e7f2013-03-26 16:21:542567def _DidYouMeanOSMacro(bad_macro):
2568 try:
2569 return {'A': 'OS_ANDROID',
2570 'B': 'OS_BSD',
2571 'C': 'OS_CHROMEOS',
2572 'F': 'OS_FREEBSD',
2573 'L': 'OS_LINUX',
2574 'M': 'OS_MACOSX',
2575 'N': 'OS_NACL',
2576 'O': 'OS_OPENBSD',
2577 'P': 'OS_POSIX',
2578 'S': 'OS_SOLARIS',
2579 'W': 'OS_WIN'}[bad_macro[3].upper()]
2580 except KeyError:
2581 return ''
2582
2583
2584def _CheckForInvalidOSMacrosInFile(input_api, f):
2585 """Check for sensible looking, totally invalid OS macros."""
2586 preprocessor_statement = input_api.re.compile(r'^\s*#')
2587 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2588 results = []
2589 for lnum, line in f.ChangedContents():
2590 if preprocessor_statement.search(line):
2591 for match in os_macro.finditer(line):
2592 if not match.group(1) in _VALID_OS_MACROS:
2593 good = _DidYouMeanOSMacro(match.group(1))
2594 did_you_mean = ' (did you mean %s?)' % good if good else ''
2595 results.append(' %s:%d %s%s' % (f.LocalPath(),
2596 lnum,
2597 match.group(1),
2598 did_you_mean))
2599 return results
2600
2601
2602def _CheckForInvalidOSMacros(input_api, output_api):
2603 """Check all affected files for invalid OS macros."""
2604 bad_macros = []
2605 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472606 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542607 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2608
2609 if not bad_macros:
2610 return []
2611
2612 return [output_api.PresubmitError(
2613 'Possibly invalid OS macro[s] found. Please fix your code\n'
2614 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2615
lliabraa35bab3932014-10-01 12:16:442616
2617def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2618 """Check all affected files for invalid "if defined" macros."""
2619 ALWAYS_DEFINED_MACROS = (
2620 "TARGET_CPU_PPC",
2621 "TARGET_CPU_PPC64",
2622 "TARGET_CPU_68K",
2623 "TARGET_CPU_X86",
2624 "TARGET_CPU_ARM",
2625 "TARGET_CPU_MIPS",
2626 "TARGET_CPU_SPARC",
2627 "TARGET_CPU_ALPHA",
2628 "TARGET_IPHONE_SIMULATOR",
2629 "TARGET_OS_EMBEDDED",
2630 "TARGET_OS_IPHONE",
2631 "TARGET_OS_MAC",
2632 "TARGET_OS_UNIX",
2633 "TARGET_OS_WIN32",
2634 )
2635 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2636 results = []
2637 for lnum, line in f.ChangedContents():
2638 for match in ifdef_macro.finditer(line):
2639 if match.group(1) in ALWAYS_DEFINED_MACROS:
2640 always_defined = ' %s is always defined. ' % match.group(1)
2641 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2642 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2643 lnum,
2644 always_defined,
2645 did_you_mean))
2646 return results
2647
2648
2649def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2650 """Check all affected files for invalid "if defined" macros."""
2651 bad_macros = []
2652 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212653 if f.LocalPath().startswith('third_party/sqlite/'):
2654 continue
lliabraa35bab3932014-10-01 12:16:442655 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2656 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2657
2658 if not bad_macros:
2659 return []
2660
2661 return [output_api.PresubmitError(
2662 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2663 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2664 bad_macros)]
2665
2666
mlamouria82272622014-09-16 18:45:042667def _CheckForIPCRules(input_api, output_api):
2668 """Check for same IPC rules described in
2669 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2670 """
2671 base_pattern = r'IPC_ENUM_TRAITS\('
2672 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2673 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2674
2675 problems = []
2676 for f in input_api.AffectedSourceFiles(None):
2677 local_path = f.LocalPath()
2678 if not local_path.endswith('.h'):
2679 continue
2680 for line_number, line in f.ChangedContents():
2681 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2682 problems.append(
2683 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2684
2685 if problems:
2686 return [output_api.PresubmitPromptWarning(
2687 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2688 else:
2689 return []
2690
[email protected]b00342e7f2013-03-26 16:21:542691
mostynbb639aca52015-01-07 20:31:232692def _CheckForWindowsLineEndings(input_api, output_api):
2693 """Check source code and known ascii text files for Windows style line
2694 endings.
2695 """
earthdok1b5e0ee2015-03-10 15:19:102696 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232697
2698 file_inclusion_pattern = (
2699 known_text_files,
2700 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2701 )
2702
mostynbb639aca52015-01-07 20:31:232703 problems = []
Andrew Grieve933d12e2017-10-30 20:22:532704 source_file_filter = lambda f: input_api.FilterSourceFile(
2705 f, white_list=file_inclusion_pattern, black_list=None)
2706 for f in input_api.AffectedSourceFiles(source_file_filter):
2707 for line_number, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:232708 if line.endswith('\r\n'):
Andrew Grieve933d12e2017-10-30 20:22:532709 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:232710
2711 if problems:
2712 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2713 'these files to contain Windows style line endings?\n' +
2714 '\n'.join(problems))]
2715
2716 return []
2717
2718
pastarmovj89f7ee12016-09-20 14:58:132719def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2720 lint_filters=None, verbose_level=None):
2721 """Checks that all source files use SYSLOG properly."""
2722 syslog_files = []
2723 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562724 for line_number, line in f.ChangedContents():
2725 if 'SYSLOG' in line:
2726 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2727
pastarmovj89f7ee12016-09-20 14:58:132728 if syslog_files:
2729 return [output_api.PresubmitPromptWarning(
2730 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2731 ' calls.\nFiles to check:\n', items=syslog_files)]
2732 return []
2733
2734
[email protected]1f7b4172010-01-28 01:17:342735def CheckChangeOnUpload(input_api, output_api):
2736 results = []
2737 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472738 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282739 results.extend(
jam93a6ee792017-02-08 23:59:222740 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192741 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222742 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132743 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162744 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542745 return results
[email protected]ca8d1982009-02-19 16:33:122746
2747
[email protected]1bfb8322014-04-23 01:02:412748def GetTryServerMasterForBot(bot):
2749 """Returns the Try Server master for the given bot.
2750
[email protected]0bb112362014-07-26 04:38:322751 It tries to guess the master from the bot name, but may still fail
2752 and return None. There is no longer a default master.
2753 """
2754 # Potentially ambiguous bot names are listed explicitly.
2755 master_map = {
tandriie5587792016-07-14 00:34:502756 'chromium_presubmit': 'master.tryserver.chromium.linux',
2757 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412758 }
[email protected]0bb112362014-07-26 04:38:322759 master = master_map.get(bot)
2760 if not master:
wnwen4fbaab82016-05-25 12:54:362761 if 'android' in bot:
tandriie5587792016-07-14 00:34:502762 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362763 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502764 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322765 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502766 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322767 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502768 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322769 return master
[email protected]1bfb8322014-04-23 01:02:412770
2771
[email protected]ca8d1982009-02-19 16:33:122772def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542773 results = []
[email protected]1f7b4172010-01-28 01:17:342774 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542775 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272776 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342777 input_api,
2778 output_api,
[email protected]2fdd1f362013-01-16 03:56:032779 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272780
jam93a6ee792017-02-08 23:59:222781 results.extend(
2782 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542783 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2784 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412785 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2786 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542787 return results