blob: 3f61deddeb693e7765f744537efaaa8e14eae7b1 [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 (
thomasanderson11aa41dc2017-06-08 22:22:38220 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20221 ),
222 True,
223 (
thomasanderson11aa41dc2017-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 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38440 (
441 r'/\bbase::Bind\(',
442 (
443 'Please consider using base::Bind{Once,Repeating} instead '
444 'of base::Bind. (crbug/714018)',
445 ),
446 False,
447 (),
448 ),
449 (
450 r'/\bbase::Callback<',
451 (
452 'Please consider using base::{Once,Repeating}Callback instead '
453 'of base::Callback. (crbug/714018)',
454 ),
455 False,
456 (),
457 ),
458 (
459 r'/\bbase::Closure\b',
460 (
461 'Please consider using base::{Once,Repeating}Closure instead '
462 'of base::Closure. (crbug/714018)',
463 ),
464 False,
465 (),
466 ),
[email protected]127f18ec2012-06-16 05:05:59467)
468
wnwenbdc444e2016-05-25 13:44:15469
mlamouria82272622014-09-16 18:45:04470_IPC_ENUM_TRAITS_DEPRECATED = (
471 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
472 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
473
Shenghua Zhangbfaa38b82017-11-16 21:58:02474_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
475 r".*[\\\/]BuildHooksAndroidImpl\.java",
476 r".*[\\\/]LicenseContentProvider\.java",
477]
[email protected]127f18ec2012-06-16 05:05:59478
Sean Kau46e29bc2017-08-28 16:31:16479# These paths contain test data and other known invalid JSON files.
480_KNOWN_INVALID_JSON_FILE_PATTERNS = [
481 r'test[\\\/]data[\\\/]',
482 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
483 r'^third_party[\\\/]protobuf[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16484 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Sean Kau46e29bc2017-08-28 16:31:16485]
486
487
[email protected]b00342e7f2013-03-26 16:21:54488_VALID_OS_MACROS = (
489 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08490 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54491 'OS_ANDROID',
492 'OS_BSD',
493 'OS_CAT', # For testing.
494 'OS_CHROMEOS',
495 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37496 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54497 'OS_IOS',
498 'OS_LINUX',
499 'OS_MACOSX',
500 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21501 'OS_NACL_NONSFI',
502 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12503 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54504 'OS_OPENBSD',
505 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37506 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54507 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54508 'OS_WIN',
509)
510
511
agrievef32bcc72016-04-04 14:57:40512_ANDROID_SPECIFIC_PYDEPS_FILES = [
513 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04514 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58515 'build/secondary/third_party/android_platform/'
516 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19517 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40518]
519
wnwenbdc444e2016-05-25 13:44:15520
agrievef32bcc72016-04-04 14:57:40521_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40522]
523
wnwenbdc444e2016-05-25 13:44:15524
agrievef32bcc72016-04-04 14:57:40525_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
526
527
[email protected]55459852011-08-10 15:17:19528def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
529 """Attempts to prevent use of functions intended only for testing in
530 non-testing code. For now this is just a best-effort implementation
531 that ignores header files and may have some false positives. A
532 better implementation would probably need a proper C++ parser.
533 """
534 # We only scan .cc files and the like, as the declaration of
535 # for-testing functions in header files are hard to distinguish from
536 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44537 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19538
jochenc0d4808c2015-07-27 09:25:42539 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19540 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09541 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19542 exclusion_pattern = input_api.re.compile(
543 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
544 base_function_pattern, base_function_pattern))
545
546 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44547 black_list = (_EXCLUDED_PATHS +
548 _TEST_CODE_EXCLUDED_PATHS +
549 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19550 return input_api.FilterSourceFile(
551 affected_file,
552 white_list=(file_inclusion_pattern, ),
553 black_list=black_list)
554
555 problems = []
556 for f in input_api.AffectedSourceFiles(FilterFile):
557 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24558 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03559 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46560 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03561 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19562 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03563 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19564
565 if problems:
[email protected]f7051d52013-04-02 18:31:42566 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03567 else:
568 return []
[email protected]55459852011-08-10 15:17:19569
570
[email protected]10689ca2011-09-02 02:31:54571def _CheckNoIOStreamInHeaders(input_api, output_api):
572 """Checks to make sure no .h files include <iostream>."""
573 files = []
574 pattern = input_api.re.compile(r'^#include\s*<iostream>',
575 input_api.re.MULTILINE)
576 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
577 if not f.LocalPath().endswith('.h'):
578 continue
579 contents = input_api.ReadFile(f)
580 if pattern.search(contents):
581 files.append(f)
582
583 if len(files):
yolandyandaabc6d2016-04-18 18:29:39584 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06585 'Do not #include <iostream> in header files, since it inserts static '
586 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54587 '#include <ostream>. See http://crbug.com/94794',
588 files) ]
589 return []
590
591
[email protected]72df4e782012-06-21 16:28:18592def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52593 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18594 problems = []
595 for f in input_api.AffectedFiles():
596 if (not f.LocalPath().endswith(('.cc', '.mm'))):
597 continue
598
599 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04600 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18601 problems.append(' %s:%d' % (f.LocalPath(), line_num))
602
603 if not problems:
604 return []
605 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
606 '\n'.join(problems))]
607
608
danakj61c1aa22015-10-26 19:55:52609def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57610 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52611 errors = []
612 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
613 input_api.re.MULTILINE)
614 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
615 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
616 continue
617 for lnum, line in f.ChangedContents():
618 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17619 errors.append(output_api.PresubmitError(
620 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57621 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17622 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52623 return errors
624
625
mcasasb7440c282015-02-04 14:52:19626def _FindHistogramNameInLine(histogram_name, line):
627 """Tries to find a histogram name or prefix in a line."""
628 if not "affected-histogram" in line:
629 return histogram_name in line
630 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
631 # the histogram_name.
632 if not '"' in line:
633 return False
634 histogram_prefix = line.split('\"')[1]
635 return histogram_prefix in histogram_name
636
637
638def _CheckUmaHistogramChanges(input_api, output_api):
639 """Check that UMA histogram names in touched lines can still be found in other
640 lines of the patch or in histograms.xml. Note that this check would not catch
641 the reverse: changes in histograms.xml not matched in the code itself."""
642 touched_histograms = []
643 histograms_xml_modifications = []
644 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
645 for f in input_api.AffectedFiles():
646 # If histograms.xml itself is modified, keep the modified lines for later.
647 if f.LocalPath().endswith(('histograms.xml')):
648 histograms_xml_modifications = f.ChangedContents()
649 continue
650 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
651 continue
652 for line_num, line in f.ChangedContents():
653 found = pattern.search(line)
654 if found:
655 touched_histograms.append([found.group(1), f, line_num])
656
657 # Search for the touched histogram names in the local modifications to
658 # histograms.xml, and, if not found, on the base histograms.xml file.
659 unmatched_histograms = []
660 for histogram_info in touched_histograms:
661 histogram_name_found = False
662 for line_num, line in histograms_xml_modifications:
663 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
664 if histogram_name_found:
665 break
666 if not histogram_name_found:
667 unmatched_histograms.append(histogram_info)
668
eromanb90c82e7e32015-04-01 15:13:49669 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19670 problems = []
671 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49672 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19673 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45674 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19675 histogram_name_found = False
676 for line in histograms_xml:
677 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
678 if histogram_name_found:
679 break
680 if not histogram_name_found:
681 problems.append(' [%s:%d] %s' %
682 (f.LocalPath(), line_num, histogram_name))
683
684 if not problems:
685 return []
686 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
687 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49688 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19689
wnwenbdc444e2016-05-25 13:44:15690
yolandyandaabc6d2016-04-18 18:29:39691def _CheckFlakyTestUsage(input_api, output_api):
692 """Check that FlakyTest annotation is our own instead of the android one"""
693 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
694 files = []
695 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
696 if f.LocalPath().endswith('Test.java'):
697 if pattern.search(input_api.ReadFile(f)):
698 files.append(f)
699 if len(files):
700 return [output_api.PresubmitError(
701 'Use org.chromium.base.test.util.FlakyTest instead of '
702 'android.test.FlakyTest',
703 files)]
704 return []
mcasasb7440c282015-02-04 14:52:19705
wnwenbdc444e2016-05-25 13:44:15706
[email protected]8ea5d4b2011-09-13 21:49:22707def _CheckNoNewWStrings(input_api, output_api):
708 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27709 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22710 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20711 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57712 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34713 '/win/' in f.LocalPath() or
714 'chrome_elf' in f.LocalPath() or
715 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20716 continue
[email protected]8ea5d4b2011-09-13 21:49:22717
[email protected]a11dbe9b2012-08-07 01:32:58718 allowWString = False
[email protected]b5c24292011-11-28 14:38:20719 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58720 if 'presubmit: allow wstring' in line:
721 allowWString = True
722 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27723 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58724 allowWString = False
725 else:
726 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22727
[email protected]55463aa62011-10-12 00:48:27728 if not problems:
729 return []
730 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58731 ' If you are calling a cross-platform API that accepts a wstring, '
732 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27733 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22734
735
[email protected]2a8ac9c2011-10-19 17:20:44736def _CheckNoDEPSGIT(input_api, output_api):
737 """Make sure .DEPS.git is never modified manually."""
738 if any(f.LocalPath().endswith('.DEPS.git') for f in
739 input_api.AffectedFiles()):
740 return [output_api.PresubmitError(
741 'Never commit changes to .DEPS.git. This file is maintained by an\n'
742 'automated system based on what\'s in DEPS and your changes will be\n'
743 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34744 '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:44745 'for more information')]
746 return []
747
748
tandriief664692014-09-23 14:51:47749def _CheckValidHostsInDEPS(input_api, output_api):
750 """Checks that DEPS file deps are from allowed_hosts."""
751 # Run only if DEPS file has been modified to annoy fewer bystanders.
752 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
753 return []
754 # Outsource work to gclient verify
755 try:
756 input_api.subprocess.check_output(['gclient', 'verify'])
757 return []
758 except input_api.subprocess.CalledProcessError, error:
759 return [output_api.PresubmitError(
760 'DEPS file must have only git dependencies.',
761 long_text=error.output)]
762
763
[email protected]127f18ec2012-06-16 05:05:59764def _CheckNoBannedFunctions(input_api, output_api):
765 """Make sure that banned functions are not used."""
766 warnings = []
767 errors = []
768
wnwenbdc444e2016-05-25 13:44:15769 def IsBlacklisted(affected_file, blacklist):
770 local_path = affected_file.LocalPath()
771 for item in blacklist:
772 if input_api.re.match(item, local_path):
773 return True
774 return False
775
776 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
777 matched = False
778 if func_name[0:1] == '/':
779 regex = func_name[1:]
780 if input_api.re.search(regex, line):
781 matched = True
782 elif func_name in line:
dchenge07de812016-06-20 19:27:17783 matched = True
wnwenbdc444e2016-05-25 13:44:15784 if matched:
dchenge07de812016-06-20 19:27:17785 problems = warnings
wnwenbdc444e2016-05-25 13:44:15786 if error:
dchenge07de812016-06-20 19:27:17787 problems = errors
wnwenbdc444e2016-05-25 13:44:15788 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
789 for message_line in message:
790 problems.append(' %s' % message_line)
791
Eric Stevensona9a980972017-09-23 00:04:41792 file_filter = lambda f: f.LocalPath().endswith(('.java'))
793 for f in input_api.AffectedFiles(file_filter=file_filter):
794 for line_num, line in f.ChangedContents():
795 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
796 CheckForMatch(f, line_num, line, func_name, message, error)
797
[email protected]127f18ec2012-06-16 05:05:59798 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
799 for f in input_api.AffectedFiles(file_filter=file_filter):
800 for line_num, line in f.ChangedContents():
801 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15802 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59803
804 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
805 for f in input_api.AffectedFiles(file_filter=file_filter):
806 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49807 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49808 if IsBlacklisted(f, excluded_paths):
809 continue
wnwenbdc444e2016-05-25 13:44:15810 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59811
812 result = []
813 if (warnings):
814 result.append(output_api.PresubmitPromptWarning(
815 'Banned functions were used.\n' + '\n'.join(warnings)))
816 if (errors):
817 result.append(output_api.PresubmitError(
818 'Banned functions were used.\n' + '\n'.join(errors)))
819 return result
820
821
[email protected]6c063c62012-07-11 19:11:06822def _CheckNoPragmaOnce(input_api, output_api):
823 """Make sure that banned functions are not used."""
824 files = []
825 pattern = input_api.re.compile(r'^#pragma\s+once',
826 input_api.re.MULTILINE)
827 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
828 if not f.LocalPath().endswith('.h'):
829 continue
830 contents = input_api.ReadFile(f)
831 if pattern.search(contents):
832 files.append(f)
833
834 if files:
835 return [output_api.PresubmitError(
836 'Do not use #pragma once in header files.\n'
837 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
838 files)]
839 return []
840
[email protected]127f18ec2012-06-16 05:05:59841
[email protected]e7479052012-09-19 00:26:12842def _CheckNoTrinaryTrueFalse(input_api, output_api):
843 """Checks to make sure we don't introduce use of foo ? true : false."""
844 problems = []
845 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
846 for f in input_api.AffectedFiles():
847 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
848 continue
849
850 for line_num, line in f.ChangedContents():
851 if pattern.match(line):
852 problems.append(' %s:%d' % (f.LocalPath(), line_num))
853
854 if not problems:
855 return []
856 return [output_api.PresubmitPromptWarning(
857 'Please consider avoiding the "? true : false" pattern if possible.\n' +
858 '\n'.join(problems))]
859
860
[email protected]55f9f382012-07-31 11:02:18861def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28862 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18863 change. Breaking - rules is an error, breaking ! rules is a
864 warning.
865 """
mohan.reddyf21db962014-10-16 12:26:47866 import sys
[email protected]55f9f382012-07-31 11:02:18867 # We need to wait until we have an input_api object and use this
868 # roundabout construct to import checkdeps because this file is
869 # eval-ed and thus doesn't have __file__.
870 original_sys_path = sys.path
871 try:
872 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47873 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18874 import checkdeps
875 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:24876 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:28877 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18878 from rules import Rule
879 finally:
880 # Restore sys.path to what it was before.
881 sys.path = original_sys_path
882
883 added_includes = []
rhalavati08acd232017-04-03 07:23:28884 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:24885 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:18886 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28887 if CppChecker.IsCppFile(f.LocalPath()):
888 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08889 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:28890 elif ProtoChecker.IsProtoFile(f.LocalPath()):
891 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08892 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:24893 elif JavaChecker.IsJavaFile(f.LocalPath()):
894 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08895 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18896
[email protected]26385172013-05-09 23:11:35897 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18898
899 error_descriptions = []
900 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28901 error_subjects = set()
902 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18903 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
904 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:08905 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18906 description_with_path = '%s\n %s' % (path, rule_description)
907 if rule_type == Rule.DISALLOW:
908 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28909 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18910 else:
911 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28912 warning_subjects.add("#includes")
913
914 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
915 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:08916 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:28917 description_with_path = '%s\n %s' % (path, rule_description)
918 if rule_type == Rule.DISALLOW:
919 error_descriptions.append(description_with_path)
920 error_subjects.add("imports")
921 else:
922 warning_descriptions.append(description_with_path)
923 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18924
Jinsuk Kim5a092672017-10-24 22:42:24925 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:02926 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:08927 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:24928 description_with_path = '%s\n %s' % (path, rule_description)
929 if rule_type == Rule.DISALLOW:
930 error_descriptions.append(description_with_path)
931 error_subjects.add("imports")
932 else:
933 warning_descriptions.append(description_with_path)
934 warning_subjects.add("imports")
935
[email protected]55f9f382012-07-31 11:02:18936 results = []
937 if error_descriptions:
938 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28939 'You added one or more %s that violate checkdeps rules.'
940 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18941 error_descriptions))
942 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42943 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28944 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18945 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28946 '%s? See relevant DEPS file(s) for details and contacts.' %
947 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18948 warning_descriptions))
949 return results
950
951
[email protected]fbcafe5a2012-08-08 15:31:22952def _CheckFilePermissions(input_api, output_api):
953 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15954 if input_api.platform == 'win32':
955 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29956 checkperms_tool = input_api.os_path.join(
957 input_api.PresubmitLocalPath(),
958 'tools', 'checkperms', 'checkperms.py')
959 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47960 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:39961 with input_api.CreateTemporaryFile() as file_list:
962 for f in input_api.AffectedFiles():
963 # checkperms.py file/directory arguments must be relative to the
964 # repository.
965 file_list.write(f.LocalPath() + '\n')
966 file_list.close()
967 args += ['--file-list', file_list.name]
968 try:
969 input_api.subprocess.check_output(args)
970 return []
971 except input_api.subprocess.CalledProcessError as error:
972 return [output_api.PresubmitError(
973 'checkperms.py failed:',
974 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22975
976
robertocn832f5992017-01-04 19:01:30977def _CheckTeamTags(input_api, output_api):
978 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
979 checkteamtags_tool = input_api.os_path.join(
980 input_api.PresubmitLocalPath(),
981 'tools', 'checkteamtags', 'checkteamtags.py')
982 args = [input_api.python_executable, checkteamtags_tool,
983 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22984 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30985 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
986 'OWNERS']
987 try:
988 if files:
989 input_api.subprocess.check_output(args + files)
990 return []
991 except input_api.subprocess.CalledProcessError as error:
992 return [output_api.PresubmitError(
993 'checkteamtags.py failed:',
994 long_text=error.output)]
995
996
[email protected]c8278b32012-10-30 20:35:49997def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
998 """Makes sure we don't include ui/aura/window_property.h
999 in header files.
1000 """
1001 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1002 errors = []
1003 for f in input_api.AffectedFiles():
1004 if not f.LocalPath().endswith('.h'):
1005 continue
1006 for line_num, line in f.ChangedContents():
1007 if pattern.match(line):
1008 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1009
1010 results = []
1011 if errors:
1012 results.append(output_api.PresubmitError(
1013 'Header files should not include ui/aura/window_property.h', errors))
1014 return results
1015
1016
[email protected]70ca77752012-11-20 03:45:031017def _CheckForVersionControlConflictsInFile(input_api, f):
1018 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1019 errors = []
1020 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231021 if f.LocalPath().endswith('.md'):
1022 # First-level headers in markdown look a lot like version control
1023 # conflict markers. http://daringfireball.net/projects/markdown/basics
1024 continue
[email protected]70ca77752012-11-20 03:45:031025 if pattern.match(line):
1026 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1027 return errors
1028
1029
1030def _CheckForVersionControlConflicts(input_api, output_api):
1031 """Usually this is not intentional and will cause a compile failure."""
1032 errors = []
1033 for f in input_api.AffectedFiles():
1034 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1035
1036 results = []
1037 if errors:
1038 results.append(output_api.PresubmitError(
1039 'Version control conflict markers found, please resolve.', errors))
1040 return results
1041
estadee17314a02017-01-12 16:22:161042def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1043 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1044 errors = []
1045 for f in input_api.AffectedFiles():
1046 for line_num, line in f.ChangedContents():
1047 if pattern.search(line):
1048 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1049
1050 results = []
1051 if errors:
1052 results.append(output_api.PresubmitPromptWarning(
1053 'Found Google support URL addressed by answer number. Please replace with '
1054 'a p= identifier instead. See crbug.com/679462\n', errors))
1055 return results
1056
[email protected]70ca77752012-11-20 03:45:031057
[email protected]06e6d0ff2012-12-11 01:36:441058def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1059 def FilterFile(affected_file):
1060 """Filter function for use with input_api.AffectedSourceFiles,
1061 below. This filters out everything except non-test files from
1062 top-level directories that generally speaking should not hard-code
1063 service URLs (e.g. src/android_webview/, src/content/ and others).
1064 """
1065 return input_api.FilterSourceFile(
1066 affected_file,
[email protected]78bb39d62012-12-11 15:11:561067 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441068 black_list=(_EXCLUDED_PATHS +
1069 _TEST_CODE_EXCLUDED_PATHS +
1070 input_api.DEFAULT_BLACK_LIST))
1071
reillyi38965732015-11-16 18:27:331072 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1073 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461074 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1075 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441076 problems = [] # items are (filename, line_number, line)
1077 for f in input_api.AffectedSourceFiles(FilterFile):
1078 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461079 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441080 problems.append((f.LocalPath(), line_num, line))
1081
1082 if problems:
[email protected]f7051d52013-04-02 18:31:421083 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441084 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581085 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441086 [' %s:%d: %s' % (
1087 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031088 else:
1089 return []
[email protected]06e6d0ff2012-12-11 01:36:441090
1091
[email protected]d2530012013-01-25 16:39:271092def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1093 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311094 The native_client_sdk directory is excluded because it has auto-generated PNG
1095 files for documentation.
[email protected]d2530012013-01-25 16:39:271096 """
[email protected]d2530012013-01-25 16:39:271097 errors = []
binji0dcdf342014-12-12 18:32:311098 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1099 black_list = (r'^native_client_sdk[\\\/]',)
1100 file_filter = lambda f: input_api.FilterSourceFile(
1101 f, white_list=white_list, black_list=black_list)
1102 for f in input_api.AffectedFiles(include_deletes=False,
1103 file_filter=file_filter):
1104 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271105
1106 results = []
1107 if errors:
1108 results.append(output_api.PresubmitError(
1109 'The name of PNG files should not have abbreviations. \n'
1110 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1111 'Contact [email protected] if you have questions.', errors))
1112 return results
1113
1114
Daniel Cheng4dcdb6b2017-04-13 08:30:171115def _ExtractAddRulesFromParsedDeps(parsed_deps):
1116 """Extract the rules that add dependencies from a parsed DEPS file.
1117
1118 Args:
1119 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1120 add_rules = set()
1121 add_rules.update([
1122 rule[1:] for rule in parsed_deps.get('include_rules', [])
1123 if rule.startswith('+') or rule.startswith('!')
1124 ])
1125 for specific_file, rules in parsed_deps.get('specific_include_rules',
1126 {}).iteritems():
1127 add_rules.update([
1128 rule[1:] for rule in rules
1129 if rule.startswith('+') or rule.startswith('!')
1130 ])
1131 return add_rules
1132
1133
1134def _ParseDeps(contents):
1135 """Simple helper for parsing DEPS files."""
1136 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171137 class _VarImpl:
1138
1139 def __init__(self, local_scope):
1140 self._local_scope = local_scope
1141
1142 def Lookup(self, var_name):
1143 """Implements the Var syntax."""
1144 try:
1145 return self._local_scope['vars'][var_name]
1146 except KeyError:
1147 raise Exception('Var is not defined: %s' % var_name)
1148
1149 local_scope = {}
1150 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171151 'Var': _VarImpl(local_scope).Lookup,
1152 }
1153 exec contents in global_scope, local_scope
1154 return local_scope
1155
1156
1157def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081158 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411159 a set of DEPS entries that we should look up.
1160
1161 For a directory (rather than a specific filename) we fake a path to
1162 a specific filename by adding /DEPS. This is chosen as a file that
1163 will seldom or never be subject to per-file include_rules.
1164 """
[email protected]2b438d62013-11-14 17:54:141165 # We ignore deps entries on auto-generated directories.
1166 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081167
Daniel Cheng4dcdb6b2017-04-13 08:30:171168 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1169 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1170
1171 added_deps = new_deps.difference(old_deps)
1172
[email protected]2b438d62013-11-14 17:54:141173 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171174 for added_dep in added_deps:
1175 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1176 continue
1177 # Assume that a rule that ends in .h is a rule for a specific file.
1178 if added_dep.endswith('.h'):
1179 results.add(added_dep)
1180 else:
1181 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081182 return results
1183
1184
[email protected]e871964c2013-05-13 14:14:551185def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1186 """When a dependency prefixed with + is added to a DEPS file, we
1187 want to make sure that the change is reviewed by an OWNER of the
1188 target file or directory, to avoid layering violations from being
1189 introduced. This check verifies that this happens.
1190 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171191 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241192
1193 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191194 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241195 for f in input_api.AffectedFiles(include_deletes=False,
1196 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551197 filename = input_api.os_path.basename(f.LocalPath())
1198 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171199 virtual_depended_on_files.update(_CalculateAddedDeps(
1200 input_api.os_path,
1201 '\n'.join(f.OldContents()),
1202 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551203
[email protected]e871964c2013-05-13 14:14:551204 if not virtual_depended_on_files:
1205 return []
1206
1207 if input_api.is_committing:
1208 if input_api.tbr:
1209 return [output_api.PresubmitNotifyResult(
1210 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271211 if input_api.dry_run:
1212 return [output_api.PresubmitNotifyResult(
1213 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551214 if not input_api.change.issue:
1215 return [output_api.PresubmitError(
1216 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401217 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551218 output = output_api.PresubmitError
1219 else:
1220 output = output_api.PresubmitNotifyResult
1221
1222 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501223 owner_email, reviewers = (
1224 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1225 input_api,
1226 owners_db.email_regexp,
1227 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551228
1229 owner_email = owner_email or input_api.change.author_email
1230
[email protected]de4f7d22013-05-23 14:27:461231 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511232 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461233 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551234 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1235 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411236
1237 # We strip the /DEPS part that was added by
1238 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1239 # directory.
1240 def StripDeps(path):
1241 start_deps = path.rfind('/DEPS')
1242 if start_deps != -1:
1243 return path[:start_deps]
1244 else:
1245 return path
1246 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551247 for path in missing_files]
1248
1249 if unapproved_dependencies:
1250 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151251 output('You need LGTM from owners of depends-on paths in DEPS that were '
1252 'modified in this CL:\n %s' %
1253 '\n '.join(sorted(unapproved_dependencies)))]
1254 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1255 output_list.append(output(
1256 'Suggested missing target path OWNERS:\n %s' %
1257 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551258 return output_list
1259
1260 return []
1261
1262
[email protected]85218562013-11-22 07:41:401263def _CheckSpamLogging(input_api, output_api):
1264 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1265 black_list = (_EXCLUDED_PATHS +
1266 _TEST_CODE_EXCLUDED_PATHS +
1267 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501268 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191269 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481270 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461271 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121272 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1273 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581274 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591275 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161276 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031277 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151278 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1279 r"^chromecast[\\\/]",
1280 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481281 r"^components[\\\/]browser_watcher[\\\/]"
1282 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311283 r"^components[\\\/]html_viewer[\\\/]"
1284 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461285 # TODO(peter): Remove this exception. https://crbug.com/534537
1286 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1287 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251288 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1289 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241290 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111291 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151292 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111293 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521294 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501295 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361296 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311297 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131298 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001299 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441300 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451301 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021302 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351303 r"dump_file_system.cc$",
1304 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401305 source_file_filter = lambda x: input_api.FilterSourceFile(
1306 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1307
thomasanderson625d3932017-03-29 07:16:581308 log_info = set([])
1309 printf = set([])
[email protected]85218562013-11-22 07:41:401310
1311 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581312 for _, line in f.ChangedContents():
1313 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1314 log_info.add(f.LocalPath())
1315 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1316 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371317
thomasanderson625d3932017-03-29 07:16:581318 if input_api.re.search(r"\bprintf\(", line):
1319 printf.add(f.LocalPath())
1320 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1321 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401322
1323 if log_info:
1324 return [output_api.PresubmitError(
1325 'These files spam the console log with LOG(INFO):',
1326 items=log_info)]
1327 if printf:
1328 return [output_api.PresubmitError(
1329 'These files spam the console log with printf/fprintf:',
1330 items=printf)]
1331 return []
1332
1333
[email protected]49aa76a2013-12-04 06:59:161334def _CheckForAnonymousVariables(input_api, output_api):
1335 """These types are all expected to hold locks while in scope and
1336 so should never be anonymous (which causes them to be immediately
1337 destroyed)."""
1338 they_who_must_be_named = [
1339 'base::AutoLock',
1340 'base::AutoReset',
1341 'base::AutoUnlock',
1342 'SkAutoAlphaRestore',
1343 'SkAutoBitmapShaderInstall',
1344 'SkAutoBlitterChoose',
1345 'SkAutoBounderCommit',
1346 'SkAutoCallProc',
1347 'SkAutoCanvasRestore',
1348 'SkAutoCommentBlock',
1349 'SkAutoDescriptor',
1350 'SkAutoDisableDirectionCheck',
1351 'SkAutoDisableOvalCheck',
1352 'SkAutoFree',
1353 'SkAutoGlyphCache',
1354 'SkAutoHDC',
1355 'SkAutoLockColors',
1356 'SkAutoLockPixels',
1357 'SkAutoMalloc',
1358 'SkAutoMaskFreeImage',
1359 'SkAutoMutexAcquire',
1360 'SkAutoPathBoundsUpdate',
1361 'SkAutoPDFRelease',
1362 'SkAutoRasterClipValidate',
1363 'SkAutoRef',
1364 'SkAutoTime',
1365 'SkAutoTrace',
1366 'SkAutoUnref',
1367 ]
1368 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1369 # bad: base::AutoLock(lock.get());
1370 # not bad: base::AutoLock lock(lock.get());
1371 bad_pattern = input_api.re.compile(anonymous)
1372 # good: new base::AutoLock(lock.get())
1373 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1374 errors = []
1375
1376 for f in input_api.AffectedFiles():
1377 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1378 continue
1379 for linenum, line in f.ChangedContents():
1380 if bad_pattern.search(line) and not good_pattern.search(line):
1381 errors.append('%s:%d' % (f.LocalPath(), linenum))
1382
1383 if errors:
1384 return [output_api.PresubmitError(
1385 'These lines create anonymous variables that need to be named:',
1386 items=errors)]
1387 return []
1388
1389
[email protected]999261d2014-03-03 20:08:081390def _CheckUserActionUpdate(input_api, output_api):
1391 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521392 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081393 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521394 # If actions.xml is already included in the changelist, the PRESUBMIT
1395 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081396 return []
1397
[email protected]999261d2014-03-03 20:08:081398 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1399 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521400 current_actions = None
[email protected]999261d2014-03-03 20:08:081401 for f in input_api.AffectedFiles(file_filter=file_filter):
1402 for line_num, line in f.ChangedContents():
1403 match = input_api.re.search(action_re, line)
1404 if match:
[email protected]2f92dec2014-03-07 19:21:521405 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1406 # loaded only once.
1407 if not current_actions:
1408 with open('tools/metrics/actions/actions.xml') as actions_f:
1409 current_actions = actions_f.read()
1410 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081411 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521412 action = 'name="{0}"'.format(action_name)
1413 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081414 return [output_api.PresubmitPromptWarning(
1415 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521416 'tools/metrics/actions/actions.xml. Please run '
1417 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081418 % (f.LocalPath(), line_num, action_name))]
1419 return []
1420
1421
Daniel Cheng13ca61a882017-08-25 15:11:251422def _ImportJSONCommentEater(input_api):
1423 import sys
1424 sys.path = sys.path + [input_api.os_path.join(
1425 input_api.PresubmitLocalPath(),
1426 'tools', 'json_comment_eater')]
1427 import json_comment_eater
1428 return json_comment_eater
1429
1430
[email protected]99171a92014-06-03 08:44:471431def _GetJSONParseError(input_api, filename, eat_comments=True):
1432 try:
1433 contents = input_api.ReadFile(filename)
1434 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251435 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131436 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471437
1438 input_api.json.loads(contents)
1439 except ValueError as e:
1440 return e
1441 return None
1442
1443
1444def _GetIDLParseError(input_api, filename):
1445 try:
1446 contents = input_api.ReadFile(filename)
1447 idl_schema = input_api.os_path.join(
1448 input_api.PresubmitLocalPath(),
1449 'tools', 'json_schema_compiler', 'idl_schema.py')
1450 process = input_api.subprocess.Popen(
1451 [input_api.python_executable, idl_schema],
1452 stdin=input_api.subprocess.PIPE,
1453 stdout=input_api.subprocess.PIPE,
1454 stderr=input_api.subprocess.PIPE,
1455 universal_newlines=True)
1456 (_, error) = process.communicate(input=contents)
1457 return error or None
1458 except ValueError as e:
1459 return e
1460
1461
1462def _CheckParseErrors(input_api, output_api):
1463 """Check that IDL and JSON files do not contain syntax errors."""
1464 actions = {
1465 '.idl': _GetIDLParseError,
1466 '.json': _GetJSONParseError,
1467 }
[email protected]99171a92014-06-03 08:44:471468 # Most JSON files are preprocessed and support comments, but these do not.
1469 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491470 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471471 ]
1472 # Only run IDL checker on files in these directories.
1473 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491474 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1475 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471476 ]
1477
1478 def get_action(affected_file):
1479 filename = affected_file.LocalPath()
1480 return actions.get(input_api.os_path.splitext(filename)[1])
1481
[email protected]99171a92014-06-03 08:44:471482 def FilterFile(affected_file):
1483 action = get_action(affected_file)
1484 if not action:
1485 return False
1486 path = affected_file.LocalPath()
1487
Sean Kau46e29bc2017-08-28 16:31:161488 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471489 return False
1490
1491 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161492 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471493 return False
1494 return True
1495
1496 results = []
1497 for affected_file in input_api.AffectedFiles(
1498 file_filter=FilterFile, include_deletes=False):
1499 action = get_action(affected_file)
1500 kwargs = {}
1501 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161502 _MatchesFile(input_api, json_no_comments_patterns,
1503 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471504 kwargs['eat_comments'] = False
1505 parse_error = action(input_api,
1506 affected_file.AbsoluteLocalPath(),
1507 **kwargs)
1508 if parse_error:
1509 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1510 (affected_file.LocalPath(), parse_error)))
1511 return results
1512
1513
[email protected]760deea2013-12-10 19:33:491514def _CheckJavaStyle(input_api, output_api):
1515 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471516 import sys
[email protected]760deea2013-12-10 19:33:491517 original_sys_path = sys.path
1518 try:
1519 sys.path = sys.path + [input_api.os_path.join(
1520 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1521 import checkstyle
1522 finally:
1523 # Restore sys.path to what it was before.
1524 sys.path = original_sys_path
1525
1526 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091527 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511528 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491529
1530
Sean Kau46e29bc2017-08-28 16:31:161531def _MatchesFile(input_api, patterns, path):
1532 for pattern in patterns:
1533 if input_api.re.search(pattern, path):
1534 return True
1535 return False
1536
1537
Daniel Cheng7052cdf2017-11-21 19:23:291538def _GetOwnersFilesToCheckForIpcOwners(input_api):
1539 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:171540
Daniel Cheng7052cdf2017-11-21 19:23:291541 Returns:
1542 A dictionary mapping an OWNER file to the list of OWNERS rules it must
1543 contain to cover IPC-related files with noparent reviewer rules.
1544 """
1545 # Whether or not a file affects IPC is (mostly) determined by a simple list
1546 # of filename patterns.
dchenge07de812016-06-20 19:27:171547 file_patterns = [
palmerb19a0932017-01-24 04:00:311548 # Legacy IPC:
dchenge07de812016-06-20 19:27:171549 '*_messages.cc',
1550 '*_messages*.h',
1551 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311552 # Mojo IPC:
dchenge07de812016-06-20 19:27:171553 '*.mojom',
1554 '*_struct_traits*.*',
1555 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311556 '*.typemap',
1557 # Android native IPC:
1558 '*.aidl',
1559 # Blink uses a different file naming convention:
1560 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171561 '*StructTraits*.*',
1562 '*TypeConverter*.*',
1563 ]
1564
scottmg7a6ed5ba2016-11-04 18:22:041565 # These third_party directories do not contain IPCs, but contain files
1566 # matching the above patterns, which trigger false positives.
1567 exclude_paths = [
1568 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291569 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041570 ]
1571
dchenge07de812016-06-20 19:27:171572 # Dictionary mapping an OWNERS file path to Patterns.
1573 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1574 # rules ) to a PatternEntry.
1575 # PatternEntry is a dictionary with two keys:
1576 # - 'files': the files that are matched by this pattern
1577 # - 'rules': the per-file rules needed for this pattern
1578 # For example, if we expect OWNERS file to contain rules for *.mojom and
1579 # *_struct_traits*.*, Patterns might look like this:
1580 # {
1581 # '*.mojom': {
1582 # 'files': ...,
1583 # 'rules': [
1584 # 'per-file *.mojom=set noparent',
1585 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1586 # ],
1587 # },
1588 # '*_struct_traits*.*': {
1589 # 'files': ...,
1590 # 'rules': [
1591 # 'per-file *_struct_traits*.*=set noparent',
1592 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1593 # ],
1594 # },
1595 # }
1596 to_check = {}
1597
Daniel Cheng13ca61a882017-08-25 15:11:251598 def AddPatternToCheck(input_file, pattern):
1599 owners_file = input_api.os_path.join(
1600 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1601 if owners_file not in to_check:
1602 to_check[owners_file] = {}
1603 if pattern not in to_check[owners_file]:
1604 to_check[owners_file][pattern] = {
1605 'files': [],
1606 'rules': [
1607 'per-file %s=set noparent' % pattern,
1608 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1609 ]
1610 }
1611 to_check[owners_file][pattern]['files'].append(f)
1612
dchenge07de812016-06-20 19:27:171613 # Iterate through the affected files to see what we actually need to check
1614 # for. We should only nag patch authors about per-file rules if a file in that
1615 # directory would match that pattern. If a directory only contains *.mojom
1616 # files and no *_messages*.h files, we should only nag about rules for
1617 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251618 for f in input_api.AffectedFiles(include_deletes=False):
1619 # Manifest files don't have a strong naming convention. Instead, scan
1620 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161621 if (f.LocalPath().endswith('.json') and
1622 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1623 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251624 json_comment_eater = _ImportJSONCommentEater(input_api)
1625 mostly_json_lines = '\n'.join(f.NewContents())
1626 # Comments aren't allowed in strict JSON, so filter them out.
1627 json_lines = json_comment_eater.Nom(mostly_json_lines)
1628 json_content = input_api.json.loads(json_lines)
1629 if 'interface_provider_specs' in json_content:
1630 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171631 for pattern in file_patterns:
1632 if input_api.fnmatch.fnmatch(
1633 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041634 skip = False
1635 for exclude in exclude_paths:
1636 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1637 skip = True
1638 break
1639 if skip:
1640 continue
Daniel Cheng13ca61a882017-08-25 15:11:251641 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171642 break
1643
Daniel Cheng7052cdf2017-11-21 19:23:291644 return to_check
1645
1646
1647def _CheckIpcOwners(input_api, output_api):
1648 """Checks that affected files involving IPC have an IPC OWNERS rule."""
1649 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
1650
1651 if to_check:
1652 # If there are any OWNERS files to check, there are IPC-related changes in
1653 # this CL. Auto-CC the review list.
1654 output_api.AppendCC('[email protected]')
1655
1656 # Go through the OWNERS files to check, filtering out rules that are already
1657 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:171658 for owners_file, patterns in to_check.iteritems():
1659 try:
1660 with file(owners_file) as f:
1661 lines = set(f.read().splitlines())
1662 for entry in patterns.itervalues():
1663 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1664 ]
1665 except IOError:
1666 # No OWNERS file, so all the rules are definitely missing.
1667 continue
1668
1669 # All the remaining lines weren't found in OWNERS files, so emit an error.
1670 errors = []
1671 for owners_file, patterns in to_check.iteritems():
1672 missing_lines = []
1673 files = []
1674 for pattern, entry in patterns.iteritems():
1675 missing_lines.extend(entry['rules'])
1676 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1677 if missing_lines:
1678 errors.append(
Daniel Cheng52111692017-06-14 08:00:591679 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171680 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1681
1682 results = []
1683 if errors:
vabrf5ce3bf92016-07-11 14:52:411684 if input_api.is_committing:
1685 output = output_api.PresubmitError
1686 else:
1687 output = output_api.PresubmitPromptWarning
1688 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591689 'Found OWNERS files that need to be updated for IPC security ' +
1690 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171691 long_text='\n\n'.join(errors)))
1692
1693 return results
1694
1695
jbriance9e12f162016-11-25 07:57:501696def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311697 """Checks that added or removed lines in non third party affected
1698 header files do not lead to new useless class or struct forward
1699 declaration.
jbriance9e12f162016-11-25 07:57:501700 """
1701 results = []
1702 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1703 input_api.re.MULTILINE)
1704 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1705 input_api.re.MULTILINE)
1706 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311707 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191708 not f.LocalPath().startswith('third_party/blink') and
1709 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311710 not f.LocalPath().startswith('third_party/WebKit') and
1711 not f.LocalPath().startswith('third_party\\WebKit')):
1712 continue
1713
jbriance9e12f162016-11-25 07:57:501714 if not f.LocalPath().endswith('.h'):
1715 continue
1716
1717 contents = input_api.ReadFile(f)
1718 fwd_decls = input_api.re.findall(class_pattern, contents)
1719 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1720
1721 useless_fwd_decls = []
1722 for decl in fwd_decls:
1723 count = sum(1 for _ in input_api.re.finditer(
1724 r'\b%s\b' % input_api.re.escape(decl), contents))
1725 if count == 1:
1726 useless_fwd_decls.append(decl)
1727
1728 if not useless_fwd_decls:
1729 continue
1730
1731 for line in f.GenerateScmDiff().splitlines():
1732 if (line.startswith('-') and not line.startswith('--') or
1733 line.startswith('+') and not line.startswith('++')):
1734 for decl in useless_fwd_decls:
1735 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1736 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241737 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501738 (f.LocalPath(), decl)))
1739 useless_fwd_decls.remove(decl)
1740
1741 return results
1742
1743
dskiba88634f4e2015-08-14 23:03:291744def _CheckAndroidToastUsage(input_api, output_api):
1745 """Checks that code uses org.chromium.ui.widget.Toast instead of
1746 android.widget.Toast (Chromium Toast doesn't force hardware
1747 acceleration on low-end devices, saving memory).
1748 """
1749 toast_import_pattern = input_api.re.compile(
1750 r'^import android\.widget\.Toast;$')
1751
1752 errors = []
1753
1754 sources = lambda affected_file: input_api.FilterSourceFile(
1755 affected_file,
1756 black_list=(_EXCLUDED_PATHS +
1757 _TEST_CODE_EXCLUDED_PATHS +
1758 input_api.DEFAULT_BLACK_LIST +
1759 (r'^chromecast[\\\/].*',
1760 r'^remoting[\\\/].*')),
1761 white_list=(r'.*\.java$',))
1762
1763 for f in input_api.AffectedSourceFiles(sources):
1764 for line_num, line in f.ChangedContents():
1765 if toast_import_pattern.search(line):
1766 errors.append("%s:%d" % (f.LocalPath(), line_num))
1767
1768 results = []
1769
1770 if errors:
1771 results.append(output_api.PresubmitError(
1772 'android.widget.Toast usage is detected. Android toasts use hardware'
1773 ' acceleration, and can be\ncostly on low-end devices. Please use'
1774 ' org.chromium.ui.widget.Toast instead.\n'
1775 'Contact [email protected] if you have any questions.',
1776 errors))
1777
1778 return results
1779
1780
dgnaa68d5e2015-06-10 10:08:221781def _CheckAndroidCrLogUsage(input_api, output_api):
1782 """Checks that new logs using org.chromium.base.Log:
1783 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511784 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221785 """
pkotwicza1dd0b002016-05-16 14:41:041786
torne89540622017-03-24 19:41:301787 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041788 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301789 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041790 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301791 # WebView license viewer code cannot depend on //base; used in stub APK.
1792 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1793 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041794 ]
1795
dgnaa68d5e2015-06-10 10:08:221796 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121797 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1798 class_in_base_pattern = input_api.re.compile(
1799 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1800 has_some_log_import_pattern = input_api.re.compile(
1801 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221802 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121803 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221804 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511805 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221806 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221807
Vincent Scheib16d7b272015-09-15 18:09:071808 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221809 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041810 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1811 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121812
dgnaa68d5e2015-06-10 10:08:221813 tag_decl_errors = []
1814 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121815 tag_errors = []
dgn38736db2015-09-18 19:20:511816 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121817 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221818
1819 for f in input_api.AffectedSourceFiles(sources):
1820 file_content = input_api.ReadFile(f)
1821 has_modified_logs = False
1822
1823 # Per line checks
dgn87d9fb62015-06-12 09:15:121824 if (cr_log_import_pattern.search(file_content) or
1825 (class_in_base_pattern.search(file_content) and
1826 not has_some_log_import_pattern.search(file_content))):
1827 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221828 for line_num, line in f.ChangedContents():
1829
1830 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121831 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221832 if match:
1833 has_modified_logs = True
1834
1835 # Make sure it uses "TAG"
1836 if not match.group('tag') == 'TAG':
1837 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121838 else:
1839 # Report non cr Log function calls in changed lines
1840 for line_num, line in f.ChangedContents():
1841 if log_call_pattern.search(line):
1842 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221843
1844 # Per file checks
1845 if has_modified_logs:
1846 # Make sure the tag is using the "cr" prefix and is not too long
1847 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511848 tag_name = match.group('name') if match else None
1849 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221850 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511851 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221852 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511853 elif '.' in tag_name:
1854 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221855
1856 results = []
1857 if tag_decl_errors:
1858 results.append(output_api.PresubmitPromptWarning(
1859 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511860 '"private static final String TAG = "<package tag>".\n'
1861 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221862 tag_decl_errors))
1863
1864 if tag_length_errors:
1865 results.append(output_api.PresubmitError(
1866 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511867 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221868 tag_length_errors))
1869
1870 if tag_errors:
1871 results.append(output_api.PresubmitPromptWarning(
1872 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1873 tag_errors))
1874
dgn87d9fb62015-06-12 09:15:121875 if util_log_errors:
dgn4401aa52015-04-29 16:26:171876 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121877 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1878 util_log_errors))
1879
dgn38736db2015-09-18 19:20:511880 if tag_with_dot_errors:
1881 results.append(output_api.PresubmitPromptWarning(
1882 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1883 tag_with_dot_errors))
1884
dgn4401aa52015-04-29 16:26:171885 return results
1886
1887
Yoland Yanb92fa522017-08-28 17:37:061888def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1889 """Checks that junit.framework.* is no longer used."""
1890 deprecated_junit_framework_pattern = input_api.re.compile(
1891 r'^import junit\.framework\..*;',
1892 input_api.re.MULTILINE)
1893 sources = lambda x: input_api.FilterSourceFile(
1894 x, white_list=(r'.*\.java$',), black_list=None)
1895 errors = []
1896 for f in input_api.AffectedFiles(sources):
1897 for line_num, line in f.ChangedContents():
1898 if deprecated_junit_framework_pattern.search(line):
1899 errors.append("%s:%d" % (f.LocalPath(), line_num))
1900
1901 results = []
1902 if errors:
1903 results.append(output_api.PresubmitError(
1904 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1905 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1906 ' if you have any question.', errors))
1907 return results
1908
1909
1910def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1911 """Checks that if new Java test classes have inheritance.
1912 Either the new test class is JUnit3 test or it is a JUnit4 test class
1913 with a base class, either case is undesirable.
1914 """
1915 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1916
1917 sources = lambda x: input_api.FilterSourceFile(
1918 x, white_list=(r'.*Test\.java$',), black_list=None)
1919 errors = []
1920 for f in input_api.AffectedFiles(sources):
1921 if not f.OldContents():
1922 class_declaration_start_flag = False
1923 for line_num, line in f.ChangedContents():
1924 if class_declaration_pattern.search(line):
1925 class_declaration_start_flag = True
1926 if class_declaration_start_flag and ' extends ' in line:
1927 errors.append('%s:%d' % (f.LocalPath(), line_num))
1928 if '{' in line:
1929 class_declaration_start_flag = False
1930
1931 results = []
1932 if errors:
1933 results.append(output_api.PresubmitPromptWarning(
1934 'The newly created files include Test classes that inherits from base'
1935 ' class. Please do not use inheritance in JUnit4 tests or add new'
1936 ' JUnit3 tests. Contact [email protected] if you have any'
1937 ' questions.', errors))
1938 return results
1939
yolandyan45001472016-12-21 21:12:421940def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1941 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1942 deprecated_annotation_import_pattern = input_api.re.compile(
1943 r'^import android\.test\.suitebuilder\.annotation\..*;',
1944 input_api.re.MULTILINE)
1945 sources = lambda x: input_api.FilterSourceFile(
1946 x, white_list=(r'.*\.java$',), black_list=None)
1947 errors = []
1948 for f in input_api.AffectedFiles(sources):
1949 for line_num, line in f.ChangedContents():
1950 if deprecated_annotation_import_pattern.search(line):
1951 errors.append("%s:%d" % (f.LocalPath(), line_num))
1952
1953 results = []
1954 if errors:
1955 results.append(output_api.PresubmitError(
1956 'Annotations in android.test.suitebuilder.annotation have been'
1957 ' deprecated since API level 24. Please use android.support.test.filters'
1958 ' from //third_party/android_support_test_runner:runner_java instead.'
1959 ' Contact [email protected] if you have any questions.', errors))
1960 return results
1961
1962
agrieve7b6479d82015-10-07 14:24:221963def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1964 """Checks if MDPI assets are placed in a correct directory."""
1965 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1966 ('/res/drawable/' in f.LocalPath() or
1967 '/res/drawable-ldrtl/' in f.LocalPath()))
1968 errors = []
1969 for f in input_api.AffectedFiles(include_deletes=False,
1970 file_filter=file_filter):
1971 errors.append(' %s' % f.LocalPath())
1972
1973 results = []
1974 if errors:
1975 results.append(output_api.PresubmitError(
1976 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1977 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1978 '/res/drawable-ldrtl/.\n'
1979 'Contact [email protected] if you have questions.', errors))
1980 return results
1981
1982
Nate Fischer535972b2017-09-16 01:06:181983def _CheckAndroidWebkitImports(input_api, output_api):
1984 """Checks that code uses org.chromium.base.Callback instead of
1985 android.widget.ValueCallback except in the WebView glue layer.
1986 """
1987 valuecallback_import_pattern = input_api.re.compile(
1988 r'^import android\.webkit\.ValueCallback;$')
1989
1990 errors = []
1991
1992 sources = lambda affected_file: input_api.FilterSourceFile(
1993 affected_file,
1994 black_list=(_EXCLUDED_PATHS +
1995 _TEST_CODE_EXCLUDED_PATHS +
1996 input_api.DEFAULT_BLACK_LIST +
1997 (r'^android_webview[\\\/]glue[\\\/].*',)),
1998 white_list=(r'.*\.java$',))
1999
2000 for f in input_api.AffectedSourceFiles(sources):
2001 for line_num, line in f.ChangedContents():
2002 if valuecallback_import_pattern.search(line):
2003 errors.append("%s:%d" % (f.LocalPath(), line_num))
2004
2005 results = []
2006
2007 if errors:
2008 results.append(output_api.PresubmitError(
2009 'android.webkit.ValueCallback usage is detected outside of the glue'
2010 ' layer. To stay compatible with the support library, android.webkit.*'
2011 ' classes should only be used inside the glue layer and'
2012 ' org.chromium.base.Callback should be used instead.',
2013 errors))
2014
2015 return results
2016
2017
agrievef32bcc72016-04-04 14:57:402018class PydepsChecker(object):
2019 def __init__(self, input_api, pydeps_files):
2020 self._file_cache = {}
2021 self._input_api = input_api
2022 self._pydeps_files = pydeps_files
2023
2024 def _LoadFile(self, path):
2025 """Returns the list of paths within a .pydeps file relative to //."""
2026 if path not in self._file_cache:
2027 with open(path) as f:
2028 self._file_cache[path] = f.read()
2029 return self._file_cache[path]
2030
2031 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
2032 """Returns an interable of paths within the .pydep, relativized to //."""
2033 os_path = self._input_api.os_path
2034 pydeps_dir = os_path.dirname(pydeps_path)
2035 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2036 if not l.startswith('*'))
2037 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2038
2039 def _CreateFilesToPydepsMap(self):
2040 """Returns a map of local_path -> list_of_pydeps."""
2041 ret = {}
2042 for pydep_local_path in self._pydeps_files:
2043 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2044 ret.setdefault(path, []).append(pydep_local_path)
2045 return ret
2046
2047 def ComputeAffectedPydeps(self):
2048 """Returns an iterable of .pydeps files that might need regenerating."""
2049 affected_pydeps = set()
2050 file_to_pydeps_map = None
2051 for f in self._input_api.AffectedFiles(include_deletes=True):
2052 local_path = f.LocalPath()
2053 if local_path == 'DEPS':
2054 return self._pydeps_files
2055 elif local_path.endswith('.pydeps'):
2056 if local_path in self._pydeps_files:
2057 affected_pydeps.add(local_path)
2058 elif local_path.endswith('.py'):
2059 if file_to_pydeps_map is None:
2060 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2061 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2062 return affected_pydeps
2063
2064 def DetermineIfStale(self, pydeps_path):
2065 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412066 import difflib
agrievef32bcc72016-04-04 14:57:402067 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2068 cmd = old_pydeps_data[1][1:].strip()
John Budorickab2fa102017-10-06 16:59:492069 env = {
2070 'PYTHONDONTWRITEBYTECODE': '1'
2071 }
agrievef32bcc72016-04-04 14:57:402072 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorickab2fa102017-10-06 16:59:492073 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412074 old_contents = old_pydeps_data[2:]
2075 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402076 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412077 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402078
2079
2080def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2081 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:002082 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:282083 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
2084 # Mac, so skip it on other platforms.
2085 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002086 return []
agrievef32bcc72016-04-04 14:57:402087 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
2088 is_android = input_api.os_path.exists('third_party/android_tools')
2089 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2090 results = []
2091 # First, check for new / deleted .pydeps.
2092 for f in input_api.AffectedFiles(include_deletes=True):
2093 if f.LocalPath().endswith('.pydeps'):
2094 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2095 results.append(output_api.PresubmitError(
2096 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2097 'remove %s' % f.LocalPath()))
2098 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2099 results.append(output_api.PresubmitError(
2100 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2101 'include %s' % f.LocalPath()))
2102
2103 if results:
2104 return results
2105
2106 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2107
2108 for pydep_path in checker.ComputeAffectedPydeps():
2109 try:
phajdan.jr0d9878552016-11-04 10:49:412110 result = checker.DetermineIfStale(pydep_path)
2111 if result:
2112 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402113 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412114 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2115 'To regenerate, run:\n\n %s' %
2116 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402117 except input_api.subprocess.CalledProcessError as error:
2118 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2119 long_text=error.output)]
2120
2121 return results
2122
2123
glidere61efad2015-02-18 17:39:432124def _CheckSingletonInHeaders(input_api, output_api):
2125 """Checks to make sure no header files have |Singleton<|."""
2126 def FileFilter(affected_file):
2127 # It's ok for base/memory/singleton.h to have |Singleton<|.
2128 black_list = (_EXCLUDED_PATHS +
2129 input_api.DEFAULT_BLACK_LIST +
2130 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2131 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2132
sergeyu34d21222015-09-16 00:11:442133 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432134 files = []
2135 for f in input_api.AffectedSourceFiles(FileFilter):
2136 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2137 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2138 contents = input_api.ReadFile(f)
2139 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242140 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432141 pattern.search(line)):
2142 files.append(f)
2143 break
2144
2145 if files:
yolandyandaabc6d2016-04-18 18:29:392146 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442147 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432148 'Please move them to an appropriate source file so that the ' +
2149 'template gets instantiated in a single compilation unit.',
2150 files) ]
2151 return []
2152
2153
[email protected]fd20b902014-05-09 02:14:532154_DEPRECATED_CSS = [
2155 # Values
2156 ( "-webkit-box", "flex" ),
2157 ( "-webkit-inline-box", "inline-flex" ),
2158 ( "-webkit-flex", "flex" ),
2159 ( "-webkit-inline-flex", "inline-flex" ),
2160 ( "-webkit-min-content", "min-content" ),
2161 ( "-webkit-max-content", "max-content" ),
2162
2163 # Properties
2164 ( "-webkit-background-clip", "background-clip" ),
2165 ( "-webkit-background-origin", "background-origin" ),
2166 ( "-webkit-background-size", "background-size" ),
2167 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442168 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532169
2170 # Functions
2171 ( "-webkit-gradient", "gradient" ),
2172 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2173 ( "-webkit-linear-gradient", "linear-gradient" ),
2174 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2175 ( "-webkit-radial-gradient", "radial-gradient" ),
2176 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2177]
2178
dbeam1ec68ac2016-12-15 05:22:242179def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532180 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252181 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342182 documentation and iOS CSS for dom distiller
2183 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252184 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532185 results = []
dbeam070cfe62014-10-22 06:44:022186 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252187 black_list = (_EXCLUDED_PATHS +
2188 _TEST_CODE_EXCLUDED_PATHS +
2189 input_api.DEFAULT_BLACK_LIST +
2190 (r"^chrome/common/extensions/docs",
2191 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342192 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442193 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252194 r"^native_client_sdk"))
2195 file_filter = lambda f: input_api.FilterSourceFile(
2196 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532197 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2198 for line_num, line in fpath.ChangedContents():
2199 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022200 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532201 results.append(output_api.PresubmitError(
2202 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2203 (fpath.LocalPath(), line_num, deprecated_value, value)))
2204 return results
2205
mohan.reddyf21db962014-10-16 12:26:472206
dbeam070cfe62014-10-22 06:44:022207_DEPRECATED_JS = [
2208 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2209 ( "__defineGetter__", "Object.defineProperty" ),
2210 ( "__defineSetter__", "Object.defineProperty" ),
2211]
2212
dbeam1ec68ac2016-12-15 05:22:242213def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022214 """Make sure that we don't use deprecated JS in Chrome code."""
2215 results = []
2216 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2217 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2218 input_api.DEFAULT_BLACK_LIST)
2219 file_filter = lambda f: input_api.FilterSourceFile(
2220 f, white_list=file_inclusion_pattern, black_list=black_list)
2221 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2222 for lnum, line in fpath.ChangedContents():
2223 for (deprecated, replacement) in _DEPRECATED_JS:
2224 if deprecated in line:
2225 results.append(output_api.PresubmitError(
2226 "%s:%d: Use of deprecated JS %s, use %s instead" %
2227 (fpath.LocalPath(), lnum, deprecated, replacement)))
2228 return results
2229
dpapadd651231d82017-07-21 02:44:472230def _CheckForRiskyJsArrowFunction(line_number, line):
2231 if ' => ' in line:
2232 return "line %d, is using an => (arrow) function\n %s\n" % (
2233 line_number, line)
2234 return ''
2235
2236def _CheckForRiskyJsConstLet(input_api, line_number, line):
2237 if input_api.re.match('^\s*(const|let)\s', line):
2238 return "line %d, is using const/let keyword\n %s\n" % (
2239 line_number, line)
2240 return ''
dbeam070cfe62014-10-22 06:44:022241
dbeam1ec68ac2016-12-15 05:22:242242def _CheckForRiskyJsFeatures(input_api, output_api):
2243 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002244 # 'ui/webui/resources/cr_components are not allowed on ios'
2245 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572246 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002247 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472248 results = []
dbeam1ec68ac2016-12-15 05:22:242249 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472250 arrow_error_lines = []
2251 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242252 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472253 arrow_error_lines += filter(None, [
2254 _CheckForRiskyJsArrowFunction(lnum, line),
2255 ])
dbeam1ec68ac2016-12-15 05:22:242256
dpapadd651231d82017-07-21 02:44:472257 const_let_error_lines += filter(None, [
2258 _CheckForRiskyJsConstLet(input_api, lnum, line),
2259 ])
dbeam1ec68ac2016-12-15 05:22:242260
dpapadd651231d82017-07-21 02:44:472261 if arrow_error_lines:
2262 arrow_error_lines = map(
2263 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2264 results.append(
2265 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2266"""
2267Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242268%s
2269Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2270https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472271""" % f.LocalPath()
2272 ])))
dbeam1ec68ac2016-12-15 05:22:242273
dpapadd651231d82017-07-21 02:44:472274 if const_let_error_lines:
2275 const_let_error_lines = map(
2276 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2277 results.append(
2278 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2279"""
2280Use of const/let keywords detected in:
2281%s
2282Please ensure your code does not run on iOS9 because const/let is not fully
2283supported.
2284https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2285https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2286""" % f.LocalPath()
2287 ])))
2288
2289 return results
dbeam1ec68ac2016-12-15 05:22:242290
rlanday6802cf632017-05-30 17:48:362291def _CheckForRelativeIncludes(input_api, output_api):
2292 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2293 import sys
2294 original_sys_path = sys.path
2295 try:
2296 sys.path = sys.path + [input_api.os_path.join(
2297 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2298 from cpp_checker import CppChecker
2299 finally:
2300 # Restore sys.path to what it was before.
2301 sys.path = original_sys_path
2302
2303 bad_files = {}
2304 for f in input_api.AffectedFiles(include_deletes=False):
2305 if (f.LocalPath().startswith('third_party') and
2306 not f.LocalPath().startswith('third_party/WebKit') and
2307 not f.LocalPath().startswith('third_party\\WebKit')):
2308 continue
2309
2310 if not CppChecker.IsCppFile(f.LocalPath()):
2311 continue
2312
2313 relative_includes = [line for line_num, line in f.ChangedContents()
2314 if "#include" in line and "../" in line]
2315 if not relative_includes:
2316 continue
2317 bad_files[f.LocalPath()] = relative_includes
2318
2319 if not bad_files:
2320 return []
2321
2322 error_descriptions = []
2323 for file_path, bad_lines in bad_files.iteritems():
2324 error_description = file_path
2325 for line in bad_lines:
2326 error_description += '\n ' + line
2327 error_descriptions.append(error_description)
2328
2329 results = []
2330 results.append(output_api.PresubmitError(
2331 'You added one or more relative #include paths (including "../").\n'
2332 'These shouldn\'t be used because they can be used to include headers\n'
2333 'from code that\'s not correctly specified as a dependency in the\n'
2334 'relevant BUILD.gn file(s).',
2335 error_descriptions))
2336
2337 return results
2338
Takeshi Yoshinoe387aa32017-08-02 13:16:132339
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202340def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2341 if not isinstance(key, ast.Str):
2342 return 'Key at line %d must be a string literal' % key.lineno
2343 if not isinstance(value, ast.Dict):
2344 return 'Value at line %d must be a dict' % value.lineno
2345 if len(value.keys) != 1:
2346 return 'Dict at line %d must have single entry' % value.lineno
2347 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2348 return (
2349 'Entry at line %d must have a string literal \'filepath\' as key' %
2350 value.lineno)
2351 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132352
Takeshi Yoshinoe387aa32017-08-02 13:16:132353
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202354def _CheckWatchlistsEntrySyntax(key, value, ast):
2355 if not isinstance(key, ast.Str):
2356 return 'Key at line %d must be a string literal' % key.lineno
2357 if not isinstance(value, ast.List):
2358 return 'Value at line %d must be a list' % value.lineno
2359 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132360
Takeshi Yoshinoe387aa32017-08-02 13:16:132361
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202362def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2363 mismatch_template = (
2364 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2365 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132366
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202367 i = 0
2368 last_key = ''
2369 while True:
2370 if i >= len(wd_dict.keys):
2371 if i >= len(w_dict.keys):
2372 return None
2373 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2374 elif i >= len(w_dict.keys):
2375 return (
2376 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132377
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202378 wd_key = wd_dict.keys[i]
2379 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132380
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202381 result = _CheckWatchlistDefinitionsEntrySyntax(
2382 wd_key, wd_dict.values[i], ast)
2383 if result is not None:
2384 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132385
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202386 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2387 if result is not None:
2388 return 'Bad entry in WATCHLISTS dict: %s' % result
2389
2390 if wd_key.s != w_key.s:
2391 return mismatch_template % (
2392 '%s at line %d' % (wd_key.s, wd_key.lineno),
2393 '%s at line %d' % (w_key.s, w_key.lineno))
2394
2395 if wd_key.s < last_key:
2396 return (
2397 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2398 (wd_key.lineno, w_key.lineno))
2399 last_key = wd_key.s
2400
2401 i = i + 1
2402
2403
2404def _CheckWATCHLISTSSyntax(expression, ast):
2405 if not isinstance(expression, ast.Expression):
2406 return 'WATCHLISTS file must contain a valid expression'
2407 dictionary = expression.body
2408 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2409 return 'WATCHLISTS file must have single dict with exactly two entries'
2410
2411 first_key = dictionary.keys[0]
2412 first_value = dictionary.values[0]
2413 second_key = dictionary.keys[1]
2414 second_value = dictionary.values[1]
2415
2416 if (not isinstance(first_key, ast.Str) or
2417 first_key.s != 'WATCHLIST_DEFINITIONS' or
2418 not isinstance(first_value, ast.Dict)):
2419 return (
2420 'The first entry of the dict in WATCHLISTS file must be '
2421 'WATCHLIST_DEFINITIONS dict')
2422
2423 if (not isinstance(second_key, ast.Str) or
2424 second_key.s != 'WATCHLISTS' or
2425 not isinstance(second_value, ast.Dict)):
2426 return (
2427 'The second entry of the dict in WATCHLISTS file must be '
2428 'WATCHLISTS dict')
2429
2430 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132431
2432
2433def _CheckWATCHLISTS(input_api, output_api):
2434 for f in input_api.AffectedFiles(include_deletes=False):
2435 if f.LocalPath() == 'WATCHLISTS':
2436 contents = input_api.ReadFile(f, 'r')
2437
2438 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202439 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132440 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202441 # Get an AST tree for it and scan the tree for detailed style checking.
2442 expression = input_api.ast.parse(
2443 contents, filename='WATCHLISTS', mode='eval')
2444 except ValueError as e:
2445 return [output_api.PresubmitError(
2446 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2447 except SyntaxError as e:
2448 return [output_api.PresubmitError(
2449 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2450 except TypeError as e:
2451 return [output_api.PresubmitError(
2452 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132453
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202454 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2455 if result is not None:
2456 return [output_api.PresubmitError(result)]
2457 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132458
2459 return []
2460
2461
dgnaa68d5e2015-06-10 10:08:222462def _AndroidSpecificOnUploadChecks(input_api, output_api):
2463 """Groups checks that target android code."""
2464 results = []
dgnaa68d5e2015-06-10 10:08:222465 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222466 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292467 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062468 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2469 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422470 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182471 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222472 return results
2473
2474
[email protected]22c9bd72011-03-27 16:47:392475def _CommonChecks(input_api, output_api):
2476 """Checks common to both upload and commit."""
2477 results = []
2478 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382479 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542480 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582481 results.extend(
2482 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192483 results.extend(
[email protected]760deea2013-12-10 19:33:492484 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542485 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182486 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522487 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222488 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442489 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592490 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062491 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122492 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182493 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222494 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302495 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492496 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032497 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492498 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442499 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272500 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072501 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542502 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442503 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392504 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552505 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042506 results.extend(
2507 input_api.canned_checks.CheckChangeHasNoTabs(
2508 input_api,
2509 output_api,
2510 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402511 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162512 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082513 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242514 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2515 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472516 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042517 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232518 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432519 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402520 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152521 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172522 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502523 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242524 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362525 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132526 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432527 results.extend(input_api.RunTests(
2528 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242529
2530 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2531 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2532 input_api, output_api,
2533 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382534 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392535 return results
[email protected]1f7b4172010-01-28 01:17:342536
[email protected]b337cb5b2011-01-23 21:24:052537
[email protected]b8079ae4a2012-12-05 19:56:492538def _CheckPatchFiles(input_api, output_api):
2539 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2540 if f.LocalPath().endswith(('.orig', '.rej'))]
2541 if problems:
2542 return [output_api.PresubmitError(
2543 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032544 else:
2545 return []
[email protected]b8079ae4a2012-12-05 19:56:492546
2547
Kent Tamura5a8755d2017-06-29 23:37:072548def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212549 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2550 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2551 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072552 include_re = input_api.re.compile(
2553 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2554 extension_re = input_api.re.compile(r'\.[a-z]+$')
2555 errors = []
2556 for f in input_api.AffectedFiles():
2557 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2558 continue
2559 found_line_number = None
2560 found_macro = None
2561 for line_num, line in f.ChangedContents():
2562 match = macro_re.search(line)
2563 if match:
2564 found_line_number = line_num
2565 found_macro = match.group(2)
2566 break
2567 if not found_line_number:
2568 continue
2569
2570 found_include = False
2571 for line in f.NewContents():
2572 if include_re.search(line):
2573 found_include = True
2574 break
2575 if found_include:
2576 continue
2577
2578 if not f.LocalPath().endswith('.h'):
2579 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2580 try:
2581 content = input_api.ReadFile(primary_header_path, 'r')
2582 if include_re.search(content):
2583 continue
2584 except IOError:
2585 pass
2586 errors.append('%s:%d %s macro is used without including build/'
2587 'build_config.h.'
2588 % (f.LocalPath(), found_line_number, found_macro))
2589 if errors:
2590 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2591 return []
2592
2593
[email protected]b00342e7f2013-03-26 16:21:542594def _DidYouMeanOSMacro(bad_macro):
2595 try:
2596 return {'A': 'OS_ANDROID',
2597 'B': 'OS_BSD',
2598 'C': 'OS_CHROMEOS',
2599 'F': 'OS_FREEBSD',
2600 'L': 'OS_LINUX',
2601 'M': 'OS_MACOSX',
2602 'N': 'OS_NACL',
2603 'O': 'OS_OPENBSD',
2604 'P': 'OS_POSIX',
2605 'S': 'OS_SOLARIS',
2606 'W': 'OS_WIN'}[bad_macro[3].upper()]
2607 except KeyError:
2608 return ''
2609
2610
2611def _CheckForInvalidOSMacrosInFile(input_api, f):
2612 """Check for sensible looking, totally invalid OS macros."""
2613 preprocessor_statement = input_api.re.compile(r'^\s*#')
2614 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2615 results = []
2616 for lnum, line in f.ChangedContents():
2617 if preprocessor_statement.search(line):
2618 for match in os_macro.finditer(line):
2619 if not match.group(1) in _VALID_OS_MACROS:
2620 good = _DidYouMeanOSMacro(match.group(1))
2621 did_you_mean = ' (did you mean %s?)' % good if good else ''
2622 results.append(' %s:%d %s%s' % (f.LocalPath(),
2623 lnum,
2624 match.group(1),
2625 did_you_mean))
2626 return results
2627
2628
2629def _CheckForInvalidOSMacros(input_api, output_api):
2630 """Check all affected files for invalid OS macros."""
2631 bad_macros = []
2632 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472633 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542634 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2635
2636 if not bad_macros:
2637 return []
2638
2639 return [output_api.PresubmitError(
2640 'Possibly invalid OS macro[s] found. Please fix your code\n'
2641 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2642
lliabraa35bab3932014-10-01 12:16:442643
2644def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2645 """Check all affected files for invalid "if defined" macros."""
2646 ALWAYS_DEFINED_MACROS = (
2647 "TARGET_CPU_PPC",
2648 "TARGET_CPU_PPC64",
2649 "TARGET_CPU_68K",
2650 "TARGET_CPU_X86",
2651 "TARGET_CPU_ARM",
2652 "TARGET_CPU_MIPS",
2653 "TARGET_CPU_SPARC",
2654 "TARGET_CPU_ALPHA",
2655 "TARGET_IPHONE_SIMULATOR",
2656 "TARGET_OS_EMBEDDED",
2657 "TARGET_OS_IPHONE",
2658 "TARGET_OS_MAC",
2659 "TARGET_OS_UNIX",
2660 "TARGET_OS_WIN32",
2661 )
2662 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2663 results = []
2664 for lnum, line in f.ChangedContents():
2665 for match in ifdef_macro.finditer(line):
2666 if match.group(1) in ALWAYS_DEFINED_MACROS:
2667 always_defined = ' %s is always defined. ' % match.group(1)
2668 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2669 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2670 lnum,
2671 always_defined,
2672 did_you_mean))
2673 return results
2674
2675
2676def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2677 """Check all affected files for invalid "if defined" macros."""
2678 bad_macros = []
2679 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212680 if f.LocalPath().startswith('third_party/sqlite/'):
2681 continue
lliabraa35bab3932014-10-01 12:16:442682 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2683 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2684
2685 if not bad_macros:
2686 return []
2687
2688 return [output_api.PresubmitError(
2689 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2690 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2691 bad_macros)]
2692
2693
mlamouria82272622014-09-16 18:45:042694def _CheckForIPCRules(input_api, output_api):
2695 """Check for same IPC rules described in
2696 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2697 """
2698 base_pattern = r'IPC_ENUM_TRAITS\('
2699 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2700 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2701
2702 problems = []
2703 for f in input_api.AffectedSourceFiles(None):
2704 local_path = f.LocalPath()
2705 if not local_path.endswith('.h'):
2706 continue
2707 for line_number, line in f.ChangedContents():
2708 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2709 problems.append(
2710 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2711
2712 if problems:
2713 return [output_api.PresubmitPromptWarning(
2714 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2715 else:
2716 return []
2717
[email protected]b00342e7f2013-03-26 16:21:542718
mostynbb639aca52015-01-07 20:31:232719def _CheckForWindowsLineEndings(input_api, output_api):
2720 """Check source code and known ascii text files for Windows style line
2721 endings.
2722 """
earthdok1b5e0ee2015-03-10 15:19:102723 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232724
2725 file_inclusion_pattern = (
2726 known_text_files,
2727 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2728 )
2729
mostynbb639aca52015-01-07 20:31:232730 problems = []
Andrew Grieve933d12e2017-10-30 20:22:532731 source_file_filter = lambda f: input_api.FilterSourceFile(
2732 f, white_list=file_inclusion_pattern, black_list=None)
2733 for f in input_api.AffectedSourceFiles(source_file_filter):
2734 for line_number, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:232735 if line.endswith('\r\n'):
Andrew Grieve933d12e2017-10-30 20:22:532736 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:232737
2738 if problems:
2739 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2740 'these files to contain Windows style line endings?\n' +
2741 '\n'.join(problems))]
2742
2743 return []
2744
2745
pastarmovj89f7ee12016-09-20 14:58:132746def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2747 lint_filters=None, verbose_level=None):
2748 """Checks that all source files use SYSLOG properly."""
2749 syslog_files = []
2750 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562751 for line_number, line in f.ChangedContents():
2752 if 'SYSLOG' in line:
2753 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2754
pastarmovj89f7ee12016-09-20 14:58:132755 if syslog_files:
2756 return [output_api.PresubmitPromptWarning(
2757 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2758 ' calls.\nFiles to check:\n', items=syslog_files)]
2759 return []
2760
2761
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192762def _CheckCrbugLinksHaveHttps(input_api, output_api):
2763 """Checks that crbug(.com) links are correctly prefixed by https://"""
2764 white_list = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2765 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS)
2766 sources = lambda f: input_api.FilterSourceFile(
2767 f, white_list=white_list, black_list=black_list)
2768
2769 pattern = input_api.re.compile(r'//.*(?<!:\/\/)crbug[.com]*')
2770 problems = []
2771 for f in input_api.AffectedSourceFiles(sources):
2772 for line_num, line in f.ChangedContents():
2773 if pattern.search(line):
2774 problems.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2775
2776 if problems:
2777 return [output_api.PresubmitPromptWarning(
2778 'Found unprefixed crbug.com URL(s), consider prepending https://\n'+
2779 '\n'.join(problems))]
2780 return []
2781
2782
[email protected]1f7b4172010-01-28 01:17:342783def CheckChangeOnUpload(input_api, output_api):
2784 results = []
2785 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472786 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282787 results.extend(
jam93a6ee792017-02-08 23:59:222788 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192789 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222790 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132791 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162792 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192793 results.extend(_CheckCrbugLinksHaveHttps(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542794 return results
[email protected]ca8d1982009-02-19 16:33:122795
2796
[email protected]1bfb8322014-04-23 01:02:412797def GetTryServerMasterForBot(bot):
2798 """Returns the Try Server master for the given bot.
2799
[email protected]0bb112362014-07-26 04:38:322800 It tries to guess the master from the bot name, but may still fail
2801 and return None. There is no longer a default master.
2802 """
2803 # Potentially ambiguous bot names are listed explicitly.
2804 master_map = {
tandriie5587792016-07-14 00:34:502805 'chromium_presubmit': 'master.tryserver.chromium.linux',
2806 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412807 }
[email protected]0bb112362014-07-26 04:38:322808 master = master_map.get(bot)
2809 if not master:
wnwen4fbaab82016-05-25 12:54:362810 if 'android' in bot:
tandriie5587792016-07-14 00:34:502811 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362812 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502813 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322814 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502815 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322816 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502817 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322818 return master
[email protected]1bfb8322014-04-23 01:02:412819
2820
[email protected]ca8d1982009-02-19 16:33:122821def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542822 results = []
[email protected]1f7b4172010-01-28 01:17:342823 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542824 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272825 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342826 input_api,
2827 output_api,
[email protected]2fdd1f362013-01-16 03:56:032828 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272829
jam93a6ee792017-02-08 23:59:222830 results.extend(
2831 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542832 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2833 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412834 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2835 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542836 return results