blob: 3dec54d61613a8d54126f4fd086b69438a8a45a8 [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$",
Kenneth Russell077c8d92017-12-16 02:52:1427 # Test pages for Maps telemetry tests.
28 r"tools[\\\/]perf[\\\/]page_sets[\\\/]maps_perf_test.*",
ehmaldonado78eee2ed2017-03-28 13:16:5429 # Test pages for WebRTC telemetry tests.
30 r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4031)
[email protected]ca8d1982009-02-19 16:33:1232
wnwenbdc444e2016-05-25 13:44:1533
[email protected]06e6d0ff2012-12-11 01:36:4434# Fragment of a regular expression that matches C++ and Objective-C++
35# implementation files.
36_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
37
wnwenbdc444e2016-05-25 13:44:1538
[email protected]06e6d0ff2012-12-11 01:36:4439# Regular expression that matches code only used for test binaries
40# (best effort).
41_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4942 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4443 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
sdefresne1fccb0a2016-12-19 08:10:5344 r'.+_(api|browser|eg|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1245 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4446 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0548 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4949 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4750 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4951 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0852 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4953 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4454)
[email protected]ca8d1982009-02-19 16:33:1255
wnwenbdc444e2016-05-25 13:44:1556
[email protected]eea609a2011-11-18 13:10:1257_TEST_ONLY_WARNING = (
58 'You might be calling functions intended only for testing from\n'
59 'production code. It is OK to ignore this warning if you know what\n'
60 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5861 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1262
63
[email protected]cf9b78f2012-11-14 11:40:2864_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4065 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2166 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
67 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2868
wnwenbdc444e2016-05-25 13:44:1569
Eric Stevensona9a980972017-09-23 00:04:4170_BANNED_JAVA_FUNCTIONS = (
71 (
72 'StrictMode.allowThreadDiskReads()',
73 (
74 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
75 'directly.',
76 ),
77 False,
78 ),
79 (
80 'StrictMode.allowThreadDiskWrites()',
81 (
82 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
83 'directly.',
84 ),
85 False,
86 ),
87)
88
[email protected]127f18ec2012-06-16 05:05:5989_BANNED_OBJC_FUNCTIONS = (
90 (
91 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2092 (
93 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5994 'prohibited. Please use CrTrackingArea instead.',
95 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
96 ),
97 False,
98 ),
99 (
[email protected]eaae1972014-04-16 04:17:26100 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20101 (
102 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59103 'instead.',
104 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
105 ),
106 False,
107 ),
108 (
109 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20110 (
111 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59112 'Please use |convertPoint:(point) fromView:nil| instead.',
113 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
114 ),
115 True,
116 ),
117 (
118 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20119 (
120 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59121 'Please use |convertPoint:(point) toView:nil| instead.',
122 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
123 ),
124 True,
125 ),
126 (
127 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20128 (
129 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59130 'Please use |convertRect:(point) fromView:nil| instead.',
131 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
132 ),
133 True,
134 ),
135 (
136 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20137 (
138 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59139 'Please use |convertRect:(point) toView:nil| instead.',
140 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
141 ),
142 True,
143 ),
144 (
145 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20146 (
147 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59148 'Please use |convertSize:(point) fromView:nil| instead.',
149 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
150 ),
151 True,
152 ),
153 (
154 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20155 (
156 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59157 'Please use |convertSize:(point) toView:nil| instead.',
158 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
159 ),
160 True,
161 ),
jif65398702016-10-27 10:19:48162 (
163 r"/\s+UTF8String\s*]",
164 (
165 'The use of -[NSString UTF8String] is dangerous as it can return null',
166 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
167 'Please use |SysNSStringToUTF8| instead.',
168 ),
169 True,
170 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34171 (
172 r'__unsafe_unretained',
173 (
174 'The use of __unsafe_unretained is almost certainly wrong, unless',
175 'when interacting with NSFastEnumeration or NSInvocation.',
176 'Please use __weak in files build with ARC, nothing otherwise.',
177 ),
178 False,
179 ),
[email protected]127f18ec2012-06-16 05:05:59180)
181
182
183_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20184 # Make sure that gtest's FRIEND_TEST() macro is not used; the
185 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30186 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20187 (
thomasandersone7caaa9b2017-03-29 19:22:53188 r'\bNULL\b',
189 (
190 'New code should not use NULL. Use nullptr instead.',
191 ),
192 True,
193 (),
194 ),
195 (
[email protected]23e6cbc2012-06-16 18:51:20196 'FRIEND_TEST(',
197 (
[email protected]e3c945502012-06-26 20:01:49198 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20199 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
200 ),
201 False,
[email protected]7345da02012-11-27 14:31:49202 (),
[email protected]23e6cbc2012-06-16 18:51:20203 ),
204 (
thomasanderson4b569052016-09-14 20:15:53205 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
206 (
207 'Chrome clients wishing to select events on X windows should use',
208 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
209 'you are selecting events from the GPU process, or if you are using',
210 'an XDisplay other than gfx::GetXDisplay().',
211 ),
212 True,
213 (
214 r"^ui[\\\/]gl[\\\/].*\.cc$",
215 r"^media[\\\/]gpu[\\\/].*\.cc$",
216 r"^gpu[\\\/].*\.cc$",
217 ),
218 ),
219 (
thomasandersone043e3ce2017-06-08 00:43:20220 r'XInternAtom|xcb_intern_atom',
221 (
thomasanderson11aa41d2017-06-08 22:22:38222 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20223 ),
224 True,
225 (
thomasanderson11aa41d2017-06-08 22:22:38226 r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$",
227 r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20228 r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$",
229 ),
230 ),
231 (
tomhudsone2c14d552016-05-26 17:07:46232 'setMatrixClip',
233 (
234 'Overriding setMatrixClip() is prohibited; ',
235 'the base function is deprecated. ',
236 ),
237 True,
238 (),
239 ),
240 (
[email protected]52657f62013-05-20 05:30:31241 'SkRefPtr',
242 (
243 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22244 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31245 ),
246 True,
247 (),
248 ),
249 (
250 'SkAutoRef',
251 (
252 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22253 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31254 ),
255 True,
256 (),
257 ),
258 (
259 'SkAutoTUnref',
260 (
261 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22262 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31263 ),
264 True,
265 (),
266 ),
267 (
268 'SkAutoUnref',
269 (
270 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
271 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22272 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31273 ),
274 True,
275 (),
276 ),
[email protected]d89eec82013-12-03 14:10:59277 (
278 r'/HANDLE_EINTR\(.*close',
279 (
280 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
281 'descriptor will be closed, and it is incorrect to retry the close.',
282 'Either call close directly and ignore its return value, or wrap close',
283 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
284 ),
285 True,
286 (),
287 ),
288 (
289 r'/IGNORE_EINTR\((?!.*close)',
290 (
291 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
292 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
293 ),
294 True,
295 (
296 # Files that #define IGNORE_EINTR.
297 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
298 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
299 ),
300 ),
[email protected]ec5b3f02014-04-04 18:43:43301 (
302 r'/v8::Extension\(',
303 (
304 'Do not introduce new v8::Extensions into the code base, use',
305 'gin::Wrappable instead. See http://crbug.com/334679',
306 ),
307 True,
[email protected]f55c90ee62014-04-12 00:50:03308 (
joaodasilva718f87672014-08-30 09:25:49309 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03310 ),
[email protected]ec5b3f02014-04-04 18:43:43311 ),
skyostilf9469f72015-04-20 10:38:52312 (
jame2d1a952016-04-02 00:27:10313 '#pragma comment(lib,',
314 (
315 'Specify libraries to link with in build files and not in the source.',
316 ),
317 True,
318 (),
319 ),
fdorayc4ac18d2017-05-01 21:39:59320 (
Matt Falkenhagen82a076e02017-09-28 08:08:19321 r'/(WebThread|BrowserThread)::(FILE|FILE_USER_BLOCKING|DB|CACHE)',
Gabriel Charette664e4482017-06-13 19:55:29322 (
323 'The non-UI/IO BrowserThreads are deprecated, please migrate this',
324 'code to TaskScheduler. See https://goo.gl/mDSxKl for details.',
325 'For questions, contact base/task_scheduler/OWNERS.',
326 ),
327 True,
328 (),
329 ),
330 (
gabd52c912a2017-05-11 04:15:59331 'base::SequenceChecker',
332 (
333 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
334 ),
335 False,
336 (),
337 ),
338 (
339 'base::ThreadChecker',
340 (
341 'Consider using THREAD_CHECKER macros instead of the class directly.',
342 ),
343 False,
344 (),
345 ),
dbeamb6f4fde2017-06-15 04:03:06346 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06347 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
348 (
349 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
350 'deprecated (http://crbug.com/634507). Please avoid converting away',
351 'from the Time types in Chromium code, especially if any math is',
352 'being done on time values. For interfacing with platform/library',
353 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
354 'type converter methods instead. For faking TimeXXX values (for unit',
355 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
356 'other use cases, please contact base/time/OWNERS.',
357 ),
358 False,
359 (),
360 ),
361 (
dbeamb6f4fde2017-06-15 04:03:06362 'CallJavascriptFunctionUnsafe',
363 (
364 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
365 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
366 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
367 ),
368 False,
369 (
370 r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$',
371 r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$',
372 r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$',
373 ),
374 ),
dskiba1474c2bfd62017-07-20 02:19:24375 (
376 'leveldb::DB::Open',
377 (
378 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
379 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
380 "Chrome's tracing, making their memory usage visible.",
381 ),
382 True,
383 (
384 r'^third_party/leveldatabase/.*\.(cc|h)$',
385 ),
Gabriel Charette0592c3a2017-07-26 12:02:04386 ),
387 (
Chris Mumfordc38afb62017-10-09 17:55:08388 'leveldb::NewMemEnv',
389 (
390 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
391 'third_party/leveldatabase/leveldb_chrome.h.',
392 ),
393 True,
394 (
395 r'^third_party/leveldatabase/.*\.(cc|h)$',
396 ),
397 ),
398 (
Gabriel Charetted9839bc2017-07-29 14:17:47399 'MessageLoop::QuitWhenIdleClosure',
Gabriel Charette0592c3a2017-07-26 12:02:04400 (
Robert Liao64b7ab22017-08-04 23:03:43401 'MessageLoop::QuitWhenIdleClosure is deprecated. Please migrate to',
402 'Runloop.',
Gabriel Charette0592c3a2017-07-26 12:02:04403 ),
404 True,
405 (),
Gabriel Charetted9839bc2017-07-29 14:17:47406 ),
407 (
408 'RunLoop::QuitCurrent',
409 (
Robert Liao64b7ab22017-08-04 23:03:43410 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
411 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47412 ),
413 True,
414 (),
Gabriel Charettea44975052017-08-21 23:14:04415 ),
416 (
417 'base::ScopedMockTimeMessageLoopTaskRunner',
418 (
419 'ScopedMockTimeMessageLoopTaskRunner is deprecated.',
420 ),
421 True,
422 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57423 ),
424 (
425 r'std::regex',
426 (
427 'Using std::regex adds unnecessary binary size to Chrome. Please use',
428 're2::RE2 instead (crbug/755321)',
429 ),
430 True,
431 (),
Francois Doray43670e32017-09-27 12:40:38432 ),
433 (
434 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
435 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
436 (
437 'Use the new API in base/threading/thread_restrictions.h.',
438 ),
439 True,
440 (),
441 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38442 (
443 r'/\bbase::Bind\(',
444 (
445 'Please consider using base::Bind{Once,Repeating} instead '
446 'of base::Bind. (crbug/714018)',
447 ),
448 False,
449 (),
450 ),
451 (
452 r'/\bbase::Callback<',
453 (
454 'Please consider using base::{Once,Repeating}Callback instead '
455 'of base::Callback. (crbug/714018)',
456 ),
457 False,
458 (),
459 ),
460 (
461 r'/\bbase::Closure\b',
462 (
463 'Please consider using base::{Once,Repeating}Closure instead '
464 'of base::Closure. (crbug/714018)',
465 ),
466 False,
467 (),
468 ),
[email protected]127f18ec2012-06-16 05:05:59469)
470
wnwenbdc444e2016-05-25 13:44:15471
mlamouria82272622014-09-16 18:45:04472_IPC_ENUM_TRAITS_DEPRECATED = (
473 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
474 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
475
Shenghua Zhangbfaa38b82017-11-16 21:58:02476_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
477 r".*[\\\/]BuildHooksAndroidImpl\.java",
478 r".*[\\\/]LicenseContentProvider\.java",
479]
[email protected]127f18ec2012-06-16 05:05:59480
Sean Kau46e29bc2017-08-28 16:31:16481# These paths contain test data and other known invalid JSON files.
482_KNOWN_INVALID_JSON_FILE_PATTERNS = [
483 r'test[\\\/]data[\\\/]',
484 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
485 r'^third_party[\\\/]protobuf[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16486 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Sean Kau46e29bc2017-08-28 16:31:16487]
488
489
[email protected]b00342e7f2013-03-26 16:21:54490_VALID_OS_MACROS = (
491 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08492 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54493 'OS_ANDROID',
494 'OS_BSD',
495 'OS_CAT', # For testing.
496 'OS_CHROMEOS',
497 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37498 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54499 'OS_IOS',
500 'OS_LINUX',
501 'OS_MACOSX',
502 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21503 'OS_NACL_NONSFI',
504 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12505 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54506 'OS_OPENBSD',
507 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37508 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54509 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54510 'OS_WIN',
511)
512
513
agrievef32bcc72016-04-04 14:57:40514_ANDROID_SPECIFIC_PYDEPS_FILES = [
515 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04516 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58517 'build/secondary/third_party/android_platform/'
518 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19519 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40520]
521
wnwenbdc444e2016-05-25 13:44:15522
agrievef32bcc72016-04-04 14:57:40523_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40524]
525
wnwenbdc444e2016-05-25 13:44:15526
agrievef32bcc72016-04-04 14:57:40527_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
528
529
[email protected]55459852011-08-10 15:17:19530def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
531 """Attempts to prevent use of functions intended only for testing in
532 non-testing code. For now this is just a best-effort implementation
533 that ignores header files and may have some false positives. A
534 better implementation would probably need a proper C++ parser.
535 """
536 # We only scan .cc files and the like, as the declaration of
537 # for-testing functions in header files are hard to distinguish from
538 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44539 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19540
jochenc0d4808c2015-07-27 09:25:42541 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19542 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09543 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19544 exclusion_pattern = input_api.re.compile(
545 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
546 base_function_pattern, base_function_pattern))
547
548 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44549 black_list = (_EXCLUDED_PATHS +
550 _TEST_CODE_EXCLUDED_PATHS +
551 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19552 return input_api.FilterSourceFile(
553 affected_file,
554 white_list=(file_inclusion_pattern, ),
555 black_list=black_list)
556
557 problems = []
558 for f in input_api.AffectedSourceFiles(FilterFile):
559 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24560 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03561 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46562 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03563 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19564 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03565 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19566
567 if problems:
[email protected]f7051d52013-04-02 18:31:42568 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03569 else:
570 return []
[email protected]55459852011-08-10 15:17:19571
572
[email protected]10689ca2011-09-02 02:31:54573def _CheckNoIOStreamInHeaders(input_api, output_api):
574 """Checks to make sure no .h files include <iostream>."""
575 files = []
576 pattern = input_api.re.compile(r'^#include\s*<iostream>',
577 input_api.re.MULTILINE)
578 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
579 if not f.LocalPath().endswith('.h'):
580 continue
581 contents = input_api.ReadFile(f)
582 if pattern.search(contents):
583 files.append(f)
584
585 if len(files):
yolandyandaabc6d2016-04-18 18:29:39586 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06587 'Do not #include <iostream> in header files, since it inserts static '
588 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54589 '#include <ostream>. See http://crbug.com/94794',
590 files) ]
591 return []
592
593
[email protected]72df4e782012-06-21 16:28:18594def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52595 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18596 problems = []
597 for f in input_api.AffectedFiles():
598 if (not f.LocalPath().endswith(('.cc', '.mm'))):
599 continue
600
601 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04602 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18603 problems.append(' %s:%d' % (f.LocalPath(), line_num))
604
605 if not problems:
606 return []
607 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
608 '\n'.join(problems))]
609
610
danakj61c1aa22015-10-26 19:55:52611def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57612 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52613 errors = []
614 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
615 input_api.re.MULTILINE)
616 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
617 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
618 continue
619 for lnum, line in f.ChangedContents():
620 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17621 errors.append(output_api.PresubmitError(
622 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57623 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17624 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52625 return errors
626
627
mcasasb7440c282015-02-04 14:52:19628def _FindHistogramNameInLine(histogram_name, line):
629 """Tries to find a histogram name or prefix in a line."""
630 if not "affected-histogram" in line:
631 return histogram_name in line
632 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
633 # the histogram_name.
634 if not '"' in line:
635 return False
636 histogram_prefix = line.split('\"')[1]
637 return histogram_prefix in histogram_name
638
639
640def _CheckUmaHistogramChanges(input_api, output_api):
641 """Check that UMA histogram names in touched lines can still be found in other
642 lines of the patch or in histograms.xml. Note that this check would not catch
643 the reverse: changes in histograms.xml not matched in the code itself."""
644 touched_histograms = []
645 histograms_xml_modifications = []
646 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
647 for f in input_api.AffectedFiles():
648 # If histograms.xml itself is modified, keep the modified lines for later.
649 if f.LocalPath().endswith(('histograms.xml')):
650 histograms_xml_modifications = f.ChangedContents()
651 continue
652 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
653 continue
654 for line_num, line in f.ChangedContents():
655 found = pattern.search(line)
656 if found:
657 touched_histograms.append([found.group(1), f, line_num])
658
659 # Search for the touched histogram names in the local modifications to
660 # histograms.xml, and, if not found, on the base histograms.xml file.
661 unmatched_histograms = []
662 for histogram_info in touched_histograms:
663 histogram_name_found = False
664 for line_num, line in histograms_xml_modifications:
665 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
666 if histogram_name_found:
667 break
668 if not histogram_name_found:
669 unmatched_histograms.append(histogram_info)
670
eromanb90c82e7e32015-04-01 15:13:49671 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19672 problems = []
673 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49674 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19675 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45676 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19677 histogram_name_found = False
678 for line in histograms_xml:
679 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
680 if histogram_name_found:
681 break
682 if not histogram_name_found:
683 problems.append(' [%s:%d] %s' %
684 (f.LocalPath(), line_num, histogram_name))
685
686 if not problems:
687 return []
688 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
689 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49690 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19691
wnwenbdc444e2016-05-25 13:44:15692
yolandyandaabc6d2016-04-18 18:29:39693def _CheckFlakyTestUsage(input_api, output_api):
694 """Check that FlakyTest annotation is our own instead of the android one"""
695 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
696 files = []
697 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
698 if f.LocalPath().endswith('Test.java'):
699 if pattern.search(input_api.ReadFile(f)):
700 files.append(f)
701 if len(files):
702 return [output_api.PresubmitError(
703 'Use org.chromium.base.test.util.FlakyTest instead of '
704 'android.test.FlakyTest',
705 files)]
706 return []
mcasasb7440c282015-02-04 14:52:19707
wnwenbdc444e2016-05-25 13:44:15708
[email protected]8ea5d4b2011-09-13 21:49:22709def _CheckNoNewWStrings(input_api, output_api):
710 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27711 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22712 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20713 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57714 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34715 '/win/' in f.LocalPath() or
716 'chrome_elf' in f.LocalPath() or
717 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20718 continue
[email protected]8ea5d4b2011-09-13 21:49:22719
[email protected]a11dbe9b2012-08-07 01:32:58720 allowWString = False
[email protected]b5c24292011-11-28 14:38:20721 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58722 if 'presubmit: allow wstring' in line:
723 allowWString = True
724 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27725 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58726 allowWString = False
727 else:
728 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22729
[email protected]55463aa62011-10-12 00:48:27730 if not problems:
731 return []
732 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58733 ' If you are calling a cross-platform API that accepts a wstring, '
734 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27735 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22736
737
[email protected]2a8ac9c2011-10-19 17:20:44738def _CheckNoDEPSGIT(input_api, output_api):
739 """Make sure .DEPS.git is never modified manually."""
740 if any(f.LocalPath().endswith('.DEPS.git') for f in
741 input_api.AffectedFiles()):
742 return [output_api.PresubmitError(
743 'Never commit changes to .DEPS.git. This file is maintained by an\n'
744 'automated system based on what\'s in DEPS and your changes will be\n'
745 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34746 '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:44747 'for more information')]
748 return []
749
750
tandriief664692014-09-23 14:51:47751def _CheckValidHostsInDEPS(input_api, output_api):
752 """Checks that DEPS file deps are from allowed_hosts."""
753 # Run only if DEPS file has been modified to annoy fewer bystanders.
754 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
755 return []
756 # Outsource work to gclient verify
757 try:
758 input_api.subprocess.check_output(['gclient', 'verify'])
759 return []
760 except input_api.subprocess.CalledProcessError, error:
761 return [output_api.PresubmitError(
762 'DEPS file must have only git dependencies.',
763 long_text=error.output)]
764
765
[email protected]127f18ec2012-06-16 05:05:59766def _CheckNoBannedFunctions(input_api, output_api):
767 """Make sure that banned functions are not used."""
768 warnings = []
769 errors = []
770
wnwenbdc444e2016-05-25 13:44:15771 def IsBlacklisted(affected_file, blacklist):
772 local_path = affected_file.LocalPath()
773 for item in blacklist:
774 if input_api.re.match(item, local_path):
775 return True
776 return False
777
778 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
779 matched = False
780 if func_name[0:1] == '/':
781 regex = func_name[1:]
782 if input_api.re.search(regex, line):
783 matched = True
784 elif func_name in line:
dchenge07de812016-06-20 19:27:17785 matched = True
wnwenbdc444e2016-05-25 13:44:15786 if matched:
dchenge07de812016-06-20 19:27:17787 problems = warnings
wnwenbdc444e2016-05-25 13:44:15788 if error:
dchenge07de812016-06-20 19:27:17789 problems = errors
wnwenbdc444e2016-05-25 13:44:15790 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
791 for message_line in message:
792 problems.append(' %s' % message_line)
793
Eric Stevensona9a980972017-09-23 00:04:41794 file_filter = lambda f: f.LocalPath().endswith(('.java'))
795 for f in input_api.AffectedFiles(file_filter=file_filter):
796 for line_num, line in f.ChangedContents():
797 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
798 CheckForMatch(f, line_num, line, func_name, message, error)
799
[email protected]127f18ec2012-06-16 05:05:59800 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
801 for f in input_api.AffectedFiles(file_filter=file_filter):
802 for line_num, line in f.ChangedContents():
803 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15804 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59805
806 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
807 for f in input_api.AffectedFiles(file_filter=file_filter):
808 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49809 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49810 if IsBlacklisted(f, excluded_paths):
811 continue
wnwenbdc444e2016-05-25 13:44:15812 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59813
814 result = []
815 if (warnings):
816 result.append(output_api.PresubmitPromptWarning(
817 'Banned functions were used.\n' + '\n'.join(warnings)))
818 if (errors):
819 result.append(output_api.PresubmitError(
820 'Banned functions were used.\n' + '\n'.join(errors)))
821 return result
822
823
[email protected]6c063c62012-07-11 19:11:06824def _CheckNoPragmaOnce(input_api, output_api):
825 """Make sure that banned functions are not used."""
826 files = []
827 pattern = input_api.re.compile(r'^#pragma\s+once',
828 input_api.re.MULTILINE)
829 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
830 if not f.LocalPath().endswith('.h'):
831 continue
832 contents = input_api.ReadFile(f)
833 if pattern.search(contents):
834 files.append(f)
835
836 if files:
837 return [output_api.PresubmitError(
838 'Do not use #pragma once in header files.\n'
839 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
840 files)]
841 return []
842
[email protected]127f18ec2012-06-16 05:05:59843
[email protected]e7479052012-09-19 00:26:12844def _CheckNoTrinaryTrueFalse(input_api, output_api):
845 """Checks to make sure we don't introduce use of foo ? true : false."""
846 problems = []
847 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
848 for f in input_api.AffectedFiles():
849 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
850 continue
851
852 for line_num, line in f.ChangedContents():
853 if pattern.match(line):
854 problems.append(' %s:%d' % (f.LocalPath(), line_num))
855
856 if not problems:
857 return []
858 return [output_api.PresubmitPromptWarning(
859 'Please consider avoiding the "? true : false" pattern if possible.\n' +
860 '\n'.join(problems))]
861
862
[email protected]55f9f382012-07-31 11:02:18863def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28864 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18865 change. Breaking - rules is an error, breaking ! rules is a
866 warning.
867 """
mohan.reddyf21db962014-10-16 12:26:47868 import sys
[email protected]55f9f382012-07-31 11:02:18869 # We need to wait until we have an input_api object and use this
870 # roundabout construct to import checkdeps because this file is
871 # eval-ed and thus doesn't have __file__.
872 original_sys_path = sys.path
873 try:
874 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47875 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18876 import checkdeps
877 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:24878 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:28879 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18880 from rules import Rule
881 finally:
882 # Restore sys.path to what it was before.
883 sys.path = original_sys_path
884
885 added_includes = []
rhalavati08acd232017-04-03 07:23:28886 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:24887 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:18888 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28889 if CppChecker.IsCppFile(f.LocalPath()):
890 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08891 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:28892 elif ProtoChecker.IsProtoFile(f.LocalPath()):
893 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08894 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:24895 elif JavaChecker.IsJavaFile(f.LocalPath()):
896 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08897 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18898
[email protected]26385172013-05-09 23:11:35899 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18900
901 error_descriptions = []
902 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28903 error_subjects = set()
904 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18905 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
906 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:08907 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18908 description_with_path = '%s\n %s' % (path, rule_description)
909 if rule_type == Rule.DISALLOW:
910 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28911 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18912 else:
913 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28914 warning_subjects.add("#includes")
915
916 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
917 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:08918 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:28919 description_with_path = '%s\n %s' % (path, rule_description)
920 if rule_type == Rule.DISALLOW:
921 error_descriptions.append(description_with_path)
922 error_subjects.add("imports")
923 else:
924 warning_descriptions.append(description_with_path)
925 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18926
Jinsuk Kim5a092672017-10-24 22:42:24927 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:02928 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:08929 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:24930 description_with_path = '%s\n %s' % (path, rule_description)
931 if rule_type == Rule.DISALLOW:
932 error_descriptions.append(description_with_path)
933 error_subjects.add("imports")
934 else:
935 warning_descriptions.append(description_with_path)
936 warning_subjects.add("imports")
937
[email protected]55f9f382012-07-31 11:02:18938 results = []
939 if error_descriptions:
940 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28941 'You added one or more %s that violate checkdeps rules.'
942 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18943 error_descriptions))
944 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42945 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28946 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18947 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28948 '%s? See relevant DEPS file(s) for details and contacts.' %
949 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18950 warning_descriptions))
951 return results
952
953
[email protected]fbcafe5a2012-08-08 15:31:22954def _CheckFilePermissions(input_api, output_api):
955 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15956 if input_api.platform == 'win32':
957 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29958 checkperms_tool = input_api.os_path.join(
959 input_api.PresubmitLocalPath(),
960 'tools', 'checkperms', 'checkperms.py')
961 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47962 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:39963 with input_api.CreateTemporaryFile() as file_list:
964 for f in input_api.AffectedFiles():
965 # checkperms.py file/directory arguments must be relative to the
966 # repository.
967 file_list.write(f.LocalPath() + '\n')
968 file_list.close()
969 args += ['--file-list', file_list.name]
970 try:
971 input_api.subprocess.check_output(args)
972 return []
973 except input_api.subprocess.CalledProcessError as error:
974 return [output_api.PresubmitError(
975 'checkperms.py failed:',
976 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22977
978
robertocn832f5992017-01-04 19:01:30979def _CheckTeamTags(input_api, output_api):
980 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
981 checkteamtags_tool = input_api.os_path.join(
982 input_api.PresubmitLocalPath(),
983 'tools', 'checkteamtags', 'checkteamtags.py')
984 args = [input_api.python_executable, checkteamtags_tool,
985 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22986 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30987 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
988 'OWNERS']
989 try:
990 if files:
991 input_api.subprocess.check_output(args + files)
992 return []
993 except input_api.subprocess.CalledProcessError as error:
994 return [output_api.PresubmitError(
995 'checkteamtags.py failed:',
996 long_text=error.output)]
997
998
[email protected]c8278b32012-10-30 20:35:49999def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
1000 """Makes sure we don't include ui/aura/window_property.h
1001 in header files.
1002 """
1003 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1004 errors = []
1005 for f in input_api.AffectedFiles():
1006 if not f.LocalPath().endswith('.h'):
1007 continue
1008 for line_num, line in f.ChangedContents():
1009 if pattern.match(line):
1010 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1011
1012 results = []
1013 if errors:
1014 results.append(output_api.PresubmitError(
1015 'Header files should not include ui/aura/window_property.h', errors))
1016 return results
1017
1018
[email protected]70ca77752012-11-20 03:45:031019def _CheckForVersionControlConflictsInFile(input_api, f):
1020 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1021 errors = []
1022 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231023 if f.LocalPath().endswith('.md'):
1024 # First-level headers in markdown look a lot like version control
1025 # conflict markers. http://daringfireball.net/projects/markdown/basics
1026 continue
[email protected]70ca77752012-11-20 03:45:031027 if pattern.match(line):
1028 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1029 return errors
1030
1031
1032def _CheckForVersionControlConflicts(input_api, output_api):
1033 """Usually this is not intentional and will cause a compile failure."""
1034 errors = []
1035 for f in input_api.AffectedFiles():
1036 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1037
1038 results = []
1039 if errors:
1040 results.append(output_api.PresubmitError(
1041 'Version control conflict markers found, please resolve.', errors))
1042 return results
1043
estadee17314a02017-01-12 16:22:161044def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1045 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1046 errors = []
1047 for f in input_api.AffectedFiles():
1048 for line_num, line in f.ChangedContents():
1049 if pattern.search(line):
1050 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1051
1052 results = []
1053 if errors:
1054 results.append(output_api.PresubmitPromptWarning(
1055 'Found Google support URL addressed by answer number. Please replace with '
1056 'a p= identifier instead. See crbug.com/679462\n', errors))
1057 return results
1058
[email protected]70ca77752012-11-20 03:45:031059
[email protected]06e6d0ff2012-12-11 01:36:441060def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1061 def FilterFile(affected_file):
1062 """Filter function for use with input_api.AffectedSourceFiles,
1063 below. This filters out everything except non-test files from
1064 top-level directories that generally speaking should not hard-code
1065 service URLs (e.g. src/android_webview/, src/content/ and others).
1066 """
1067 return input_api.FilterSourceFile(
1068 affected_file,
[email protected]78bb39d62012-12-11 15:11:561069 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441070 black_list=(_EXCLUDED_PATHS +
1071 _TEST_CODE_EXCLUDED_PATHS +
1072 input_api.DEFAULT_BLACK_LIST))
1073
reillyi38965732015-11-16 18:27:331074 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1075 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461076 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1077 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441078 problems = [] # items are (filename, line_number, line)
1079 for f in input_api.AffectedSourceFiles(FilterFile):
1080 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461081 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441082 problems.append((f.LocalPath(), line_num, line))
1083
1084 if problems:
[email protected]f7051d52013-04-02 18:31:421085 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441086 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581087 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441088 [' %s:%d: %s' % (
1089 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031090 else:
1091 return []
[email protected]06e6d0ff2012-12-11 01:36:441092
1093
[email protected]d2530012013-01-25 16:39:271094def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1095 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311096 The native_client_sdk directory is excluded because it has auto-generated PNG
1097 files for documentation.
[email protected]d2530012013-01-25 16:39:271098 """
[email protected]d2530012013-01-25 16:39:271099 errors = []
binji0dcdf342014-12-12 18:32:311100 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1101 black_list = (r'^native_client_sdk[\\\/]',)
1102 file_filter = lambda f: input_api.FilterSourceFile(
1103 f, white_list=white_list, black_list=black_list)
1104 for f in input_api.AffectedFiles(include_deletes=False,
1105 file_filter=file_filter):
1106 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271107
1108 results = []
1109 if errors:
1110 results.append(output_api.PresubmitError(
1111 'The name of PNG files should not have abbreviations. \n'
1112 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1113 'Contact [email protected] if you have questions.', errors))
1114 return results
1115
1116
Daniel Cheng4dcdb6b2017-04-13 08:30:171117def _ExtractAddRulesFromParsedDeps(parsed_deps):
1118 """Extract the rules that add dependencies from a parsed DEPS file.
1119
1120 Args:
1121 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1122 add_rules = set()
1123 add_rules.update([
1124 rule[1:] for rule in parsed_deps.get('include_rules', [])
1125 if rule.startswith('+') or rule.startswith('!')
1126 ])
1127 for specific_file, rules in parsed_deps.get('specific_include_rules',
1128 {}).iteritems():
1129 add_rules.update([
1130 rule[1:] for rule in rules
1131 if rule.startswith('+') or rule.startswith('!')
1132 ])
1133 return add_rules
1134
1135
1136def _ParseDeps(contents):
1137 """Simple helper for parsing DEPS files."""
1138 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171139 class _VarImpl:
1140
1141 def __init__(self, local_scope):
1142 self._local_scope = local_scope
1143
1144 def Lookup(self, var_name):
1145 """Implements the Var syntax."""
1146 try:
1147 return self._local_scope['vars'][var_name]
1148 except KeyError:
1149 raise Exception('Var is not defined: %s' % var_name)
1150
1151 local_scope = {}
1152 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171153 'Var': _VarImpl(local_scope).Lookup,
1154 }
1155 exec contents in global_scope, local_scope
1156 return local_scope
1157
1158
1159def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081160 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411161 a set of DEPS entries that we should look up.
1162
1163 For a directory (rather than a specific filename) we fake a path to
1164 a specific filename by adding /DEPS. This is chosen as a file that
1165 will seldom or never be subject to per-file include_rules.
1166 """
[email protected]2b438d62013-11-14 17:54:141167 # We ignore deps entries on auto-generated directories.
1168 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081169
Daniel Cheng4dcdb6b2017-04-13 08:30:171170 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1171 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1172
1173 added_deps = new_deps.difference(old_deps)
1174
[email protected]2b438d62013-11-14 17:54:141175 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171176 for added_dep in added_deps:
1177 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1178 continue
1179 # Assume that a rule that ends in .h is a rule for a specific file.
1180 if added_dep.endswith('.h'):
1181 results.add(added_dep)
1182 else:
1183 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081184 return results
1185
1186
[email protected]e871964c2013-05-13 14:14:551187def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1188 """When a dependency prefixed with + is added to a DEPS file, we
1189 want to make sure that the change is reviewed by an OWNER of the
1190 target file or directory, to avoid layering violations from being
1191 introduced. This check verifies that this happens.
1192 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171193 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241194
1195 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191196 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241197 for f in input_api.AffectedFiles(include_deletes=False,
1198 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551199 filename = input_api.os_path.basename(f.LocalPath())
1200 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171201 virtual_depended_on_files.update(_CalculateAddedDeps(
1202 input_api.os_path,
1203 '\n'.join(f.OldContents()),
1204 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551205
[email protected]e871964c2013-05-13 14:14:551206 if not virtual_depended_on_files:
1207 return []
1208
1209 if input_api.is_committing:
1210 if input_api.tbr:
1211 return [output_api.PresubmitNotifyResult(
1212 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271213 if input_api.dry_run:
1214 return [output_api.PresubmitNotifyResult(
1215 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551216 if not input_api.change.issue:
1217 return [output_api.PresubmitError(
1218 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401219 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551220 output = output_api.PresubmitError
1221 else:
1222 output = output_api.PresubmitNotifyResult
1223
1224 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501225 owner_email, reviewers = (
1226 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1227 input_api,
1228 owners_db.email_regexp,
1229 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551230
1231 owner_email = owner_email or input_api.change.author_email
1232
[email protected]de4f7d22013-05-23 14:27:461233 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511234 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461235 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551236 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1237 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411238
1239 # We strip the /DEPS part that was added by
1240 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1241 # directory.
1242 def StripDeps(path):
1243 start_deps = path.rfind('/DEPS')
1244 if start_deps != -1:
1245 return path[:start_deps]
1246 else:
1247 return path
1248 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551249 for path in missing_files]
1250
1251 if unapproved_dependencies:
1252 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151253 output('You need LGTM from owners of depends-on paths in DEPS that were '
1254 'modified in this CL:\n %s' %
1255 '\n '.join(sorted(unapproved_dependencies)))]
1256 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1257 output_list.append(output(
1258 'Suggested missing target path OWNERS:\n %s' %
1259 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551260 return output_list
1261
1262 return []
1263
1264
[email protected]85218562013-11-22 07:41:401265def _CheckSpamLogging(input_api, output_api):
1266 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1267 black_list = (_EXCLUDED_PATHS +
1268 _TEST_CODE_EXCLUDED_PATHS +
1269 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501270 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191271 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481272 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461273 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121274 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1275 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581276 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591277 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161278 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031279 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151280 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1281 r"^chromecast[\\\/]",
1282 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481283 r"^components[\\\/]browser_watcher[\\\/]"
1284 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311285 r"^components[\\\/]html_viewer[\\\/]"
1286 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461287 # TODO(peter): Remove this exception. https://crbug.com/534537
1288 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1289 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251290 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1291 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241292 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111293 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151294 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111295 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521296 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501297 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361298 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311299 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131300 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001301 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441302 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451303 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021304 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351305 r"dump_file_system.cc$",
1306 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401307 source_file_filter = lambda x: input_api.FilterSourceFile(
1308 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1309
thomasanderson625d3932017-03-29 07:16:581310 log_info = set([])
1311 printf = set([])
[email protected]85218562013-11-22 07:41:401312
1313 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581314 for _, line in f.ChangedContents():
1315 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1316 log_info.add(f.LocalPath())
1317 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1318 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371319
thomasanderson625d3932017-03-29 07:16:581320 if input_api.re.search(r"\bprintf\(", line):
1321 printf.add(f.LocalPath())
1322 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1323 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401324
1325 if log_info:
1326 return [output_api.PresubmitError(
1327 'These files spam the console log with LOG(INFO):',
1328 items=log_info)]
1329 if printf:
1330 return [output_api.PresubmitError(
1331 'These files spam the console log with printf/fprintf:',
1332 items=printf)]
1333 return []
1334
1335
[email protected]49aa76a2013-12-04 06:59:161336def _CheckForAnonymousVariables(input_api, output_api):
1337 """These types are all expected to hold locks while in scope and
1338 so should never be anonymous (which causes them to be immediately
1339 destroyed)."""
1340 they_who_must_be_named = [
1341 'base::AutoLock',
1342 'base::AutoReset',
1343 'base::AutoUnlock',
1344 'SkAutoAlphaRestore',
1345 'SkAutoBitmapShaderInstall',
1346 'SkAutoBlitterChoose',
1347 'SkAutoBounderCommit',
1348 'SkAutoCallProc',
1349 'SkAutoCanvasRestore',
1350 'SkAutoCommentBlock',
1351 'SkAutoDescriptor',
1352 'SkAutoDisableDirectionCheck',
1353 'SkAutoDisableOvalCheck',
1354 'SkAutoFree',
1355 'SkAutoGlyphCache',
1356 'SkAutoHDC',
1357 'SkAutoLockColors',
1358 'SkAutoLockPixels',
1359 'SkAutoMalloc',
1360 'SkAutoMaskFreeImage',
1361 'SkAutoMutexAcquire',
1362 'SkAutoPathBoundsUpdate',
1363 'SkAutoPDFRelease',
1364 'SkAutoRasterClipValidate',
1365 'SkAutoRef',
1366 'SkAutoTime',
1367 'SkAutoTrace',
1368 'SkAutoUnref',
1369 ]
1370 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1371 # bad: base::AutoLock(lock.get());
1372 # not bad: base::AutoLock lock(lock.get());
1373 bad_pattern = input_api.re.compile(anonymous)
1374 # good: new base::AutoLock(lock.get())
1375 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1376 errors = []
1377
1378 for f in input_api.AffectedFiles():
1379 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1380 continue
1381 for linenum, line in f.ChangedContents():
1382 if bad_pattern.search(line) and not good_pattern.search(line):
1383 errors.append('%s:%d' % (f.LocalPath(), linenum))
1384
1385 if errors:
1386 return [output_api.PresubmitError(
1387 'These lines create anonymous variables that need to be named:',
1388 items=errors)]
1389 return []
1390
1391
[email protected]999261d2014-03-03 20:08:081392def _CheckUserActionUpdate(input_api, output_api):
1393 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521394 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081395 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521396 # If actions.xml is already included in the changelist, the PRESUBMIT
1397 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081398 return []
1399
[email protected]999261d2014-03-03 20:08:081400 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1401 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521402 current_actions = None
[email protected]999261d2014-03-03 20:08:081403 for f in input_api.AffectedFiles(file_filter=file_filter):
1404 for line_num, line in f.ChangedContents():
1405 match = input_api.re.search(action_re, line)
1406 if match:
[email protected]2f92dec2014-03-07 19:21:521407 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1408 # loaded only once.
1409 if not current_actions:
1410 with open('tools/metrics/actions/actions.xml') as actions_f:
1411 current_actions = actions_f.read()
1412 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081413 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521414 action = 'name="{0}"'.format(action_name)
1415 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081416 return [output_api.PresubmitPromptWarning(
1417 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521418 'tools/metrics/actions/actions.xml. Please run '
1419 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081420 % (f.LocalPath(), line_num, action_name))]
1421 return []
1422
1423
Daniel Cheng13ca61a882017-08-25 15:11:251424def _ImportJSONCommentEater(input_api):
1425 import sys
1426 sys.path = sys.path + [input_api.os_path.join(
1427 input_api.PresubmitLocalPath(),
1428 'tools', 'json_comment_eater')]
1429 import json_comment_eater
1430 return json_comment_eater
1431
1432
[email protected]99171a92014-06-03 08:44:471433def _GetJSONParseError(input_api, filename, eat_comments=True):
1434 try:
1435 contents = input_api.ReadFile(filename)
1436 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251437 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131438 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471439
1440 input_api.json.loads(contents)
1441 except ValueError as e:
1442 return e
1443 return None
1444
1445
1446def _GetIDLParseError(input_api, filename):
1447 try:
1448 contents = input_api.ReadFile(filename)
1449 idl_schema = input_api.os_path.join(
1450 input_api.PresubmitLocalPath(),
1451 'tools', 'json_schema_compiler', 'idl_schema.py')
1452 process = input_api.subprocess.Popen(
1453 [input_api.python_executable, idl_schema],
1454 stdin=input_api.subprocess.PIPE,
1455 stdout=input_api.subprocess.PIPE,
1456 stderr=input_api.subprocess.PIPE,
1457 universal_newlines=True)
1458 (_, error) = process.communicate(input=contents)
1459 return error or None
1460 except ValueError as e:
1461 return e
1462
1463
1464def _CheckParseErrors(input_api, output_api):
1465 """Check that IDL and JSON files do not contain syntax errors."""
1466 actions = {
1467 '.idl': _GetIDLParseError,
1468 '.json': _GetJSONParseError,
1469 }
[email protected]99171a92014-06-03 08:44:471470 # Most JSON files are preprocessed and support comments, but these do not.
1471 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491472 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471473 ]
1474 # Only run IDL checker on files in these directories.
1475 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491476 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1477 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471478 ]
1479
1480 def get_action(affected_file):
1481 filename = affected_file.LocalPath()
1482 return actions.get(input_api.os_path.splitext(filename)[1])
1483
[email protected]99171a92014-06-03 08:44:471484 def FilterFile(affected_file):
1485 action = get_action(affected_file)
1486 if not action:
1487 return False
1488 path = affected_file.LocalPath()
1489
Sean Kau46e29bc2017-08-28 16:31:161490 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471491 return False
1492
1493 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161494 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471495 return False
1496 return True
1497
1498 results = []
1499 for affected_file in input_api.AffectedFiles(
1500 file_filter=FilterFile, include_deletes=False):
1501 action = get_action(affected_file)
1502 kwargs = {}
1503 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161504 _MatchesFile(input_api, json_no_comments_patterns,
1505 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471506 kwargs['eat_comments'] = False
1507 parse_error = action(input_api,
1508 affected_file.AbsoluteLocalPath(),
1509 **kwargs)
1510 if parse_error:
1511 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1512 (affected_file.LocalPath(), parse_error)))
1513 return results
1514
1515
[email protected]760deea2013-12-10 19:33:491516def _CheckJavaStyle(input_api, output_api):
1517 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471518 import sys
[email protected]760deea2013-12-10 19:33:491519 original_sys_path = sys.path
1520 try:
1521 sys.path = sys.path + [input_api.os_path.join(
1522 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1523 import checkstyle
1524 finally:
1525 # Restore sys.path to what it was before.
1526 sys.path = original_sys_path
1527
1528 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091529 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511530 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491531
1532
Sean Kau46e29bc2017-08-28 16:31:161533def _MatchesFile(input_api, patterns, path):
1534 for pattern in patterns:
1535 if input_api.re.search(pattern, path):
1536 return True
1537 return False
1538
1539
Daniel Cheng7052cdf2017-11-21 19:23:291540def _GetOwnersFilesToCheckForIpcOwners(input_api):
1541 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:171542
Daniel Cheng7052cdf2017-11-21 19:23:291543 Returns:
1544 A dictionary mapping an OWNER file to the list of OWNERS rules it must
1545 contain to cover IPC-related files with noparent reviewer rules.
1546 """
1547 # Whether or not a file affects IPC is (mostly) determined by a simple list
1548 # of filename patterns.
dchenge07de812016-06-20 19:27:171549 file_patterns = [
palmerb19a0932017-01-24 04:00:311550 # Legacy IPC:
dchenge07de812016-06-20 19:27:171551 '*_messages.cc',
1552 '*_messages*.h',
1553 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311554 # Mojo IPC:
dchenge07de812016-06-20 19:27:171555 '*.mojom',
1556 '*_struct_traits*.*',
1557 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311558 '*.typemap',
1559 # Android native IPC:
1560 '*.aidl',
1561 # Blink uses a different file naming convention:
1562 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171563 '*StructTraits*.*',
1564 '*TypeConverter*.*',
1565 ]
1566
scottmg7a6ed5ba2016-11-04 18:22:041567 # These third_party directories do not contain IPCs, but contain files
1568 # matching the above patterns, which trigger false positives.
1569 exclude_paths = [
1570 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291571 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041572 ]
1573
dchenge07de812016-06-20 19:27:171574 # Dictionary mapping an OWNERS file path to Patterns.
1575 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1576 # rules ) to a PatternEntry.
1577 # PatternEntry is a dictionary with two keys:
1578 # - 'files': the files that are matched by this pattern
1579 # - 'rules': the per-file rules needed for this pattern
1580 # For example, if we expect OWNERS file to contain rules for *.mojom and
1581 # *_struct_traits*.*, Patterns might look like this:
1582 # {
1583 # '*.mojom': {
1584 # 'files': ...,
1585 # 'rules': [
1586 # 'per-file *.mojom=set noparent',
1587 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1588 # ],
1589 # },
1590 # '*_struct_traits*.*': {
1591 # 'files': ...,
1592 # 'rules': [
1593 # 'per-file *_struct_traits*.*=set noparent',
1594 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1595 # ],
1596 # },
1597 # }
1598 to_check = {}
1599
Daniel Cheng13ca61a882017-08-25 15:11:251600 def AddPatternToCheck(input_file, pattern):
1601 owners_file = input_api.os_path.join(
1602 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1603 if owners_file not in to_check:
1604 to_check[owners_file] = {}
1605 if pattern not in to_check[owners_file]:
1606 to_check[owners_file][pattern] = {
1607 'files': [],
1608 'rules': [
1609 'per-file %s=set noparent' % pattern,
1610 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1611 ]
1612 }
1613 to_check[owners_file][pattern]['files'].append(f)
1614
dchenge07de812016-06-20 19:27:171615 # Iterate through the affected files to see what we actually need to check
1616 # for. We should only nag patch authors about per-file rules if a file in that
1617 # directory would match that pattern. If a directory only contains *.mojom
1618 # files and no *_messages*.h files, we should only nag about rules for
1619 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251620 for f in input_api.AffectedFiles(include_deletes=False):
1621 # Manifest files don't have a strong naming convention. Instead, scan
1622 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161623 if (f.LocalPath().endswith('.json') and
1624 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1625 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251626 json_comment_eater = _ImportJSONCommentEater(input_api)
1627 mostly_json_lines = '\n'.join(f.NewContents())
1628 # Comments aren't allowed in strict JSON, so filter them out.
1629 json_lines = json_comment_eater.Nom(mostly_json_lines)
1630 json_content = input_api.json.loads(json_lines)
1631 if 'interface_provider_specs' in json_content:
1632 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171633 for pattern in file_patterns:
1634 if input_api.fnmatch.fnmatch(
1635 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041636 skip = False
1637 for exclude in exclude_paths:
1638 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1639 skip = True
1640 break
1641 if skip:
1642 continue
Daniel Cheng13ca61a882017-08-25 15:11:251643 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171644 break
1645
Daniel Cheng7052cdf2017-11-21 19:23:291646 return to_check
1647
1648
1649def _CheckIpcOwners(input_api, output_api):
1650 """Checks that affected files involving IPC have an IPC OWNERS rule."""
1651 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
1652
1653 if to_check:
1654 # If there are any OWNERS files to check, there are IPC-related changes in
1655 # this CL. Auto-CC the review list.
1656 output_api.AppendCC('[email protected]')
1657
1658 # Go through the OWNERS files to check, filtering out rules that are already
1659 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:171660 for owners_file, patterns in to_check.iteritems():
1661 try:
1662 with file(owners_file) as f:
1663 lines = set(f.read().splitlines())
1664 for entry in patterns.itervalues():
1665 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1666 ]
1667 except IOError:
1668 # No OWNERS file, so all the rules are definitely missing.
1669 continue
1670
1671 # All the remaining lines weren't found in OWNERS files, so emit an error.
1672 errors = []
1673 for owners_file, patterns in to_check.iteritems():
1674 missing_lines = []
1675 files = []
1676 for pattern, entry in patterns.iteritems():
1677 missing_lines.extend(entry['rules'])
1678 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1679 if missing_lines:
1680 errors.append(
Daniel Cheng52111692017-06-14 08:00:591681 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171682 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1683
1684 results = []
1685 if errors:
vabrf5ce3bf92016-07-11 14:52:411686 if input_api.is_committing:
1687 output = output_api.PresubmitError
1688 else:
1689 output = output_api.PresubmitPromptWarning
1690 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591691 'Found OWNERS files that need to be updated for IPC security ' +
1692 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171693 long_text='\n\n'.join(errors)))
1694
1695 return results
1696
1697
jbriance9e12f162016-11-25 07:57:501698def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311699 """Checks that added or removed lines in non third party affected
1700 header files do not lead to new useless class or struct forward
1701 declaration.
jbriance9e12f162016-11-25 07:57:501702 """
1703 results = []
1704 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1705 input_api.re.MULTILINE)
1706 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1707 input_api.re.MULTILINE)
1708 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311709 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191710 not f.LocalPath().startswith('third_party/blink') and
1711 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311712 not f.LocalPath().startswith('third_party/WebKit') and
1713 not f.LocalPath().startswith('third_party\\WebKit')):
1714 continue
1715
jbriance9e12f162016-11-25 07:57:501716 if not f.LocalPath().endswith('.h'):
1717 continue
1718
1719 contents = input_api.ReadFile(f)
1720 fwd_decls = input_api.re.findall(class_pattern, contents)
1721 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1722
1723 useless_fwd_decls = []
1724 for decl in fwd_decls:
1725 count = sum(1 for _ in input_api.re.finditer(
1726 r'\b%s\b' % input_api.re.escape(decl), contents))
1727 if count == 1:
1728 useless_fwd_decls.append(decl)
1729
1730 if not useless_fwd_decls:
1731 continue
1732
1733 for line in f.GenerateScmDiff().splitlines():
1734 if (line.startswith('-') and not line.startswith('--') or
1735 line.startswith('+') and not line.startswith('++')):
1736 for decl in useless_fwd_decls:
1737 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1738 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241739 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501740 (f.LocalPath(), decl)))
1741 useless_fwd_decls.remove(decl)
1742
1743 return results
1744
1745
dskiba88634f4e2015-08-14 23:03:291746def _CheckAndroidToastUsage(input_api, output_api):
1747 """Checks that code uses org.chromium.ui.widget.Toast instead of
1748 android.widget.Toast (Chromium Toast doesn't force hardware
1749 acceleration on low-end devices, saving memory).
1750 """
1751 toast_import_pattern = input_api.re.compile(
1752 r'^import android\.widget\.Toast;$')
1753
1754 errors = []
1755
1756 sources = lambda affected_file: input_api.FilterSourceFile(
1757 affected_file,
1758 black_list=(_EXCLUDED_PATHS +
1759 _TEST_CODE_EXCLUDED_PATHS +
1760 input_api.DEFAULT_BLACK_LIST +
1761 (r'^chromecast[\\\/].*',
1762 r'^remoting[\\\/].*')),
1763 white_list=(r'.*\.java$',))
1764
1765 for f in input_api.AffectedSourceFiles(sources):
1766 for line_num, line in f.ChangedContents():
1767 if toast_import_pattern.search(line):
1768 errors.append("%s:%d" % (f.LocalPath(), line_num))
1769
1770 results = []
1771
1772 if errors:
1773 results.append(output_api.PresubmitError(
1774 'android.widget.Toast usage is detected. Android toasts use hardware'
1775 ' acceleration, and can be\ncostly on low-end devices. Please use'
1776 ' org.chromium.ui.widget.Toast instead.\n'
1777 'Contact [email protected] if you have any questions.',
1778 errors))
1779
1780 return results
1781
1782
dgnaa68d5e2015-06-10 10:08:221783def _CheckAndroidCrLogUsage(input_api, output_api):
1784 """Checks that new logs using org.chromium.base.Log:
1785 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511786 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221787 """
pkotwicza1dd0b002016-05-16 14:41:041788
torne89540622017-03-24 19:41:301789 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041790 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301791 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041792 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301793 # WebView license viewer code cannot depend on //base; used in stub APK.
1794 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1795 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041796 ]
1797
dgnaa68d5e2015-06-10 10:08:221798 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121799 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1800 class_in_base_pattern = input_api.re.compile(
1801 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1802 has_some_log_import_pattern = input_api.re.compile(
1803 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221804 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121805 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221806 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511807 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221808 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221809
Vincent Scheib16d7b272015-09-15 18:09:071810 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221811 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041812 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1813 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121814
dgnaa68d5e2015-06-10 10:08:221815 tag_decl_errors = []
1816 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121817 tag_errors = []
dgn38736db2015-09-18 19:20:511818 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121819 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221820
1821 for f in input_api.AffectedSourceFiles(sources):
1822 file_content = input_api.ReadFile(f)
1823 has_modified_logs = False
1824
1825 # Per line checks
dgn87d9fb62015-06-12 09:15:121826 if (cr_log_import_pattern.search(file_content) or
1827 (class_in_base_pattern.search(file_content) and
1828 not has_some_log_import_pattern.search(file_content))):
1829 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221830 for line_num, line in f.ChangedContents():
1831
1832 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121833 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221834 if match:
1835 has_modified_logs = True
1836
1837 # Make sure it uses "TAG"
1838 if not match.group('tag') == 'TAG':
1839 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121840 else:
1841 # Report non cr Log function calls in changed lines
1842 for line_num, line in f.ChangedContents():
1843 if log_call_pattern.search(line):
1844 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221845
1846 # Per file checks
1847 if has_modified_logs:
1848 # Make sure the tag is using the "cr" prefix and is not too long
1849 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511850 tag_name = match.group('name') if match else None
1851 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221852 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511853 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221854 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511855 elif '.' in tag_name:
1856 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221857
1858 results = []
1859 if tag_decl_errors:
1860 results.append(output_api.PresubmitPromptWarning(
1861 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511862 '"private static final String TAG = "<package tag>".\n'
1863 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221864 tag_decl_errors))
1865
1866 if tag_length_errors:
1867 results.append(output_api.PresubmitError(
1868 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511869 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221870 tag_length_errors))
1871
1872 if tag_errors:
1873 results.append(output_api.PresubmitPromptWarning(
1874 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1875 tag_errors))
1876
dgn87d9fb62015-06-12 09:15:121877 if util_log_errors:
dgn4401aa52015-04-29 16:26:171878 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121879 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1880 util_log_errors))
1881
dgn38736db2015-09-18 19:20:511882 if tag_with_dot_errors:
1883 results.append(output_api.PresubmitPromptWarning(
1884 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1885 tag_with_dot_errors))
1886
dgn4401aa52015-04-29 16:26:171887 return results
1888
1889
Yoland Yanb92fa522017-08-28 17:37:061890def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1891 """Checks that junit.framework.* is no longer used."""
1892 deprecated_junit_framework_pattern = input_api.re.compile(
1893 r'^import junit\.framework\..*;',
1894 input_api.re.MULTILINE)
1895 sources = lambda x: input_api.FilterSourceFile(
1896 x, white_list=(r'.*\.java$',), black_list=None)
1897 errors = []
1898 for f in input_api.AffectedFiles(sources):
1899 for line_num, line in f.ChangedContents():
1900 if deprecated_junit_framework_pattern.search(line):
1901 errors.append("%s:%d" % (f.LocalPath(), line_num))
1902
1903 results = []
1904 if errors:
1905 results.append(output_api.PresubmitError(
1906 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1907 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1908 ' if you have any question.', errors))
1909 return results
1910
1911
1912def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1913 """Checks that if new Java test classes have inheritance.
1914 Either the new test class is JUnit3 test or it is a JUnit4 test class
1915 with a base class, either case is undesirable.
1916 """
1917 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1918
1919 sources = lambda x: input_api.FilterSourceFile(
1920 x, white_list=(r'.*Test\.java$',), black_list=None)
1921 errors = []
1922 for f in input_api.AffectedFiles(sources):
1923 if not f.OldContents():
1924 class_declaration_start_flag = False
1925 for line_num, line in f.ChangedContents():
1926 if class_declaration_pattern.search(line):
1927 class_declaration_start_flag = True
1928 if class_declaration_start_flag and ' extends ' in line:
1929 errors.append('%s:%d' % (f.LocalPath(), line_num))
1930 if '{' in line:
1931 class_declaration_start_flag = False
1932
1933 results = []
1934 if errors:
1935 results.append(output_api.PresubmitPromptWarning(
1936 'The newly created files include Test classes that inherits from base'
1937 ' class. Please do not use inheritance in JUnit4 tests or add new'
1938 ' JUnit3 tests. Contact [email protected] if you have any'
1939 ' questions.', errors))
1940 return results
1941
yolandyan45001472016-12-21 21:12:421942def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1943 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1944 deprecated_annotation_import_pattern = input_api.re.compile(
1945 r'^import android\.test\.suitebuilder\.annotation\..*;',
1946 input_api.re.MULTILINE)
1947 sources = lambda x: input_api.FilterSourceFile(
1948 x, white_list=(r'.*\.java$',), black_list=None)
1949 errors = []
1950 for f in input_api.AffectedFiles(sources):
1951 for line_num, line in f.ChangedContents():
1952 if deprecated_annotation_import_pattern.search(line):
1953 errors.append("%s:%d" % (f.LocalPath(), line_num))
1954
1955 results = []
1956 if errors:
1957 results.append(output_api.PresubmitError(
1958 'Annotations in android.test.suitebuilder.annotation have been'
1959 ' deprecated since API level 24. Please use android.support.test.filters'
1960 ' from //third_party/android_support_test_runner:runner_java instead.'
1961 ' Contact [email protected] if you have any questions.', errors))
1962 return results
1963
1964
agrieve7b6479d82015-10-07 14:24:221965def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1966 """Checks if MDPI assets are placed in a correct directory."""
1967 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1968 ('/res/drawable/' in f.LocalPath() or
1969 '/res/drawable-ldrtl/' in f.LocalPath()))
1970 errors = []
1971 for f in input_api.AffectedFiles(include_deletes=False,
1972 file_filter=file_filter):
1973 errors.append(' %s' % f.LocalPath())
1974
1975 results = []
1976 if errors:
1977 results.append(output_api.PresubmitError(
1978 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1979 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1980 '/res/drawable-ldrtl/.\n'
1981 'Contact [email protected] if you have questions.', errors))
1982 return results
1983
1984
Nate Fischer535972b2017-09-16 01:06:181985def _CheckAndroidWebkitImports(input_api, output_api):
1986 """Checks that code uses org.chromium.base.Callback instead of
1987 android.widget.ValueCallback except in the WebView glue layer.
1988 """
1989 valuecallback_import_pattern = input_api.re.compile(
1990 r'^import android\.webkit\.ValueCallback;$')
1991
1992 errors = []
1993
1994 sources = lambda affected_file: input_api.FilterSourceFile(
1995 affected_file,
1996 black_list=(_EXCLUDED_PATHS +
1997 _TEST_CODE_EXCLUDED_PATHS +
1998 input_api.DEFAULT_BLACK_LIST +
1999 (r'^android_webview[\\\/]glue[\\\/].*',)),
2000 white_list=(r'.*\.java$',))
2001
2002 for f in input_api.AffectedSourceFiles(sources):
2003 for line_num, line in f.ChangedContents():
2004 if valuecallback_import_pattern.search(line):
2005 errors.append("%s:%d" % (f.LocalPath(), line_num))
2006
2007 results = []
2008
2009 if errors:
2010 results.append(output_api.PresubmitError(
2011 'android.webkit.ValueCallback usage is detected outside of the glue'
2012 ' layer. To stay compatible with the support library, android.webkit.*'
2013 ' classes should only be used inside the glue layer and'
2014 ' org.chromium.base.Callback should be used instead.',
2015 errors))
2016
2017 return results
2018
2019
agrievef32bcc72016-04-04 14:57:402020class PydepsChecker(object):
2021 def __init__(self, input_api, pydeps_files):
2022 self._file_cache = {}
2023 self._input_api = input_api
2024 self._pydeps_files = pydeps_files
2025
2026 def _LoadFile(self, path):
2027 """Returns the list of paths within a .pydeps file relative to //."""
2028 if path not in self._file_cache:
2029 with open(path) as f:
2030 self._file_cache[path] = f.read()
2031 return self._file_cache[path]
2032
2033 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
2034 """Returns an interable of paths within the .pydep, relativized to //."""
2035 os_path = self._input_api.os_path
2036 pydeps_dir = os_path.dirname(pydeps_path)
2037 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2038 if not l.startswith('*'))
2039 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2040
2041 def _CreateFilesToPydepsMap(self):
2042 """Returns a map of local_path -> list_of_pydeps."""
2043 ret = {}
2044 for pydep_local_path in self._pydeps_files:
2045 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2046 ret.setdefault(path, []).append(pydep_local_path)
2047 return ret
2048
2049 def ComputeAffectedPydeps(self):
2050 """Returns an iterable of .pydeps files that might need regenerating."""
2051 affected_pydeps = set()
2052 file_to_pydeps_map = None
2053 for f in self._input_api.AffectedFiles(include_deletes=True):
2054 local_path = f.LocalPath()
2055 if local_path == 'DEPS':
2056 return self._pydeps_files
2057 elif local_path.endswith('.pydeps'):
2058 if local_path in self._pydeps_files:
2059 affected_pydeps.add(local_path)
2060 elif local_path.endswith('.py'):
2061 if file_to_pydeps_map is None:
2062 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2063 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2064 return affected_pydeps
2065
2066 def DetermineIfStale(self, pydeps_path):
2067 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412068 import difflib
agrievef32bcc72016-04-04 14:57:402069 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2070 cmd = old_pydeps_data[1][1:].strip()
John Budorickab2fa102017-10-06 16:59:492071 env = {
2072 'PYTHONDONTWRITEBYTECODE': '1'
2073 }
agrievef32bcc72016-04-04 14:57:402074 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorickab2fa102017-10-06 16:59:492075 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412076 old_contents = old_pydeps_data[2:]
2077 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402078 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412079 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402080
2081
2082def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2083 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:002084 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:282085 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
2086 # Mac, so skip it on other platforms.
2087 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002088 return []
agrievef32bcc72016-04-04 14:57:402089 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
2090 is_android = input_api.os_path.exists('third_party/android_tools')
2091 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2092 results = []
2093 # First, check for new / deleted .pydeps.
2094 for f in input_api.AffectedFiles(include_deletes=True):
2095 if f.LocalPath().endswith('.pydeps'):
2096 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2097 results.append(output_api.PresubmitError(
2098 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2099 'remove %s' % f.LocalPath()))
2100 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2101 results.append(output_api.PresubmitError(
2102 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2103 'include %s' % f.LocalPath()))
2104
2105 if results:
2106 return results
2107
2108 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2109
2110 for pydep_path in checker.ComputeAffectedPydeps():
2111 try:
phajdan.jr0d9878552016-11-04 10:49:412112 result = checker.DetermineIfStale(pydep_path)
2113 if result:
2114 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402115 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412116 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2117 'To regenerate, run:\n\n %s' %
2118 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402119 except input_api.subprocess.CalledProcessError as error:
2120 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2121 long_text=error.output)]
2122
2123 return results
2124
2125
glidere61efad2015-02-18 17:39:432126def _CheckSingletonInHeaders(input_api, output_api):
2127 """Checks to make sure no header files have |Singleton<|."""
2128 def FileFilter(affected_file):
2129 # It's ok for base/memory/singleton.h to have |Singleton<|.
2130 black_list = (_EXCLUDED_PATHS +
2131 input_api.DEFAULT_BLACK_LIST +
2132 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2133 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2134
sergeyu34d21222015-09-16 00:11:442135 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432136 files = []
2137 for f in input_api.AffectedSourceFiles(FileFilter):
2138 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2139 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2140 contents = input_api.ReadFile(f)
2141 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242142 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432143 pattern.search(line)):
2144 files.append(f)
2145 break
2146
2147 if files:
yolandyandaabc6d2016-04-18 18:29:392148 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442149 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432150 'Please move them to an appropriate source file so that the ' +
2151 'template gets instantiated in a single compilation unit.',
2152 files) ]
2153 return []
2154
2155
[email protected]fd20b902014-05-09 02:14:532156_DEPRECATED_CSS = [
2157 # Values
2158 ( "-webkit-box", "flex" ),
2159 ( "-webkit-inline-box", "inline-flex" ),
2160 ( "-webkit-flex", "flex" ),
2161 ( "-webkit-inline-flex", "inline-flex" ),
2162 ( "-webkit-min-content", "min-content" ),
2163 ( "-webkit-max-content", "max-content" ),
2164
2165 # Properties
2166 ( "-webkit-background-clip", "background-clip" ),
2167 ( "-webkit-background-origin", "background-origin" ),
2168 ( "-webkit-background-size", "background-size" ),
2169 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442170 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532171
2172 # Functions
2173 ( "-webkit-gradient", "gradient" ),
2174 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2175 ( "-webkit-linear-gradient", "linear-gradient" ),
2176 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2177 ( "-webkit-radial-gradient", "radial-gradient" ),
2178 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2179]
2180
dbeam1ec68ac2016-12-15 05:22:242181def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532182 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252183 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342184 documentation and iOS CSS for dom distiller
2185 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252186 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532187 results = []
dbeam070cfe62014-10-22 06:44:022188 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252189 black_list = (_EXCLUDED_PATHS +
2190 _TEST_CODE_EXCLUDED_PATHS +
2191 input_api.DEFAULT_BLACK_LIST +
2192 (r"^chrome/common/extensions/docs",
2193 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342194 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442195 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252196 r"^native_client_sdk"))
2197 file_filter = lambda f: input_api.FilterSourceFile(
2198 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532199 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2200 for line_num, line in fpath.ChangedContents():
2201 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022202 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532203 results.append(output_api.PresubmitError(
2204 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2205 (fpath.LocalPath(), line_num, deprecated_value, value)))
2206 return results
2207
mohan.reddyf21db962014-10-16 12:26:472208
dbeam070cfe62014-10-22 06:44:022209_DEPRECATED_JS = [
2210 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2211 ( "__defineGetter__", "Object.defineProperty" ),
2212 ( "__defineSetter__", "Object.defineProperty" ),
2213]
2214
dbeam1ec68ac2016-12-15 05:22:242215def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022216 """Make sure that we don't use deprecated JS in Chrome code."""
2217 results = []
2218 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2219 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2220 input_api.DEFAULT_BLACK_LIST)
2221 file_filter = lambda f: input_api.FilterSourceFile(
2222 f, white_list=file_inclusion_pattern, black_list=black_list)
2223 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2224 for lnum, line in fpath.ChangedContents():
2225 for (deprecated, replacement) in _DEPRECATED_JS:
2226 if deprecated in line:
2227 results.append(output_api.PresubmitError(
2228 "%s:%d: Use of deprecated JS %s, use %s instead" %
2229 (fpath.LocalPath(), lnum, deprecated, replacement)))
2230 return results
2231
dpapadd651231d82017-07-21 02:44:472232def _CheckForRiskyJsArrowFunction(line_number, line):
2233 if ' => ' in line:
2234 return "line %d, is using an => (arrow) function\n %s\n" % (
2235 line_number, line)
2236 return ''
2237
2238def _CheckForRiskyJsConstLet(input_api, line_number, line):
2239 if input_api.re.match('^\s*(const|let)\s', line):
2240 return "line %d, is using const/let keyword\n %s\n" % (
2241 line_number, line)
2242 return ''
dbeam070cfe62014-10-22 06:44:022243
dbeam1ec68ac2016-12-15 05:22:242244def _CheckForRiskyJsFeatures(input_api, output_api):
2245 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002246 # 'ui/webui/resources/cr_components are not allowed on ios'
2247 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572248 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002249 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472250 results = []
dbeam1ec68ac2016-12-15 05:22:242251 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472252 arrow_error_lines = []
2253 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242254 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472255 arrow_error_lines += filter(None, [
2256 _CheckForRiskyJsArrowFunction(lnum, line),
2257 ])
dbeam1ec68ac2016-12-15 05:22:242258
dpapadd651231d82017-07-21 02:44:472259 const_let_error_lines += filter(None, [
2260 _CheckForRiskyJsConstLet(input_api, lnum, line),
2261 ])
dbeam1ec68ac2016-12-15 05:22:242262
dpapadd651231d82017-07-21 02:44:472263 if arrow_error_lines:
2264 arrow_error_lines = map(
2265 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2266 results.append(
2267 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2268"""
2269Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242270%s
2271Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2272https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472273""" % f.LocalPath()
2274 ])))
dbeam1ec68ac2016-12-15 05:22:242275
dpapadd651231d82017-07-21 02:44:472276 if const_let_error_lines:
2277 const_let_error_lines = map(
2278 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2279 results.append(
2280 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2281"""
2282Use of const/let keywords detected in:
2283%s
2284Please ensure your code does not run on iOS9 because const/let is not fully
2285supported.
2286https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2287https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2288""" % f.LocalPath()
2289 ])))
2290
2291 return results
dbeam1ec68ac2016-12-15 05:22:242292
rlanday6802cf632017-05-30 17:48:362293def _CheckForRelativeIncludes(input_api, output_api):
2294 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2295 import sys
2296 original_sys_path = sys.path
2297 try:
2298 sys.path = sys.path + [input_api.os_path.join(
2299 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2300 from cpp_checker import CppChecker
2301 finally:
2302 # Restore sys.path to what it was before.
2303 sys.path = original_sys_path
2304
2305 bad_files = {}
2306 for f in input_api.AffectedFiles(include_deletes=False):
2307 if (f.LocalPath().startswith('third_party') and
2308 not f.LocalPath().startswith('third_party/WebKit') and
2309 not f.LocalPath().startswith('third_party\\WebKit')):
2310 continue
2311
2312 if not CppChecker.IsCppFile(f.LocalPath()):
2313 continue
2314
2315 relative_includes = [line for line_num, line in f.ChangedContents()
2316 if "#include" in line and "../" in line]
2317 if not relative_includes:
2318 continue
2319 bad_files[f.LocalPath()] = relative_includes
2320
2321 if not bad_files:
2322 return []
2323
2324 error_descriptions = []
2325 for file_path, bad_lines in bad_files.iteritems():
2326 error_description = file_path
2327 for line in bad_lines:
2328 error_description += '\n ' + line
2329 error_descriptions.append(error_description)
2330
2331 results = []
2332 results.append(output_api.PresubmitError(
2333 'You added one or more relative #include paths (including "../").\n'
2334 'These shouldn\'t be used because they can be used to include headers\n'
2335 'from code that\'s not correctly specified as a dependency in the\n'
2336 'relevant BUILD.gn file(s).',
2337 error_descriptions))
2338
2339 return results
2340
Takeshi Yoshinoe387aa32017-08-02 13:16:132341
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202342def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2343 if not isinstance(key, ast.Str):
2344 return 'Key at line %d must be a string literal' % key.lineno
2345 if not isinstance(value, ast.Dict):
2346 return 'Value at line %d must be a dict' % value.lineno
2347 if len(value.keys) != 1:
2348 return 'Dict at line %d must have single entry' % value.lineno
2349 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2350 return (
2351 'Entry at line %d must have a string literal \'filepath\' as key' %
2352 value.lineno)
2353 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132354
Takeshi Yoshinoe387aa32017-08-02 13:16:132355
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202356def _CheckWatchlistsEntrySyntax(key, value, ast):
2357 if not isinstance(key, ast.Str):
2358 return 'Key at line %d must be a string literal' % key.lineno
2359 if not isinstance(value, ast.List):
2360 return 'Value at line %d must be a list' % value.lineno
2361 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132362
Takeshi Yoshinoe387aa32017-08-02 13:16:132363
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202364def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2365 mismatch_template = (
2366 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2367 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132368
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202369 i = 0
2370 last_key = ''
2371 while True:
2372 if i >= len(wd_dict.keys):
2373 if i >= len(w_dict.keys):
2374 return None
2375 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2376 elif i >= len(w_dict.keys):
2377 return (
2378 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132379
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202380 wd_key = wd_dict.keys[i]
2381 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132382
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202383 result = _CheckWatchlistDefinitionsEntrySyntax(
2384 wd_key, wd_dict.values[i], ast)
2385 if result is not None:
2386 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132387
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202388 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2389 if result is not None:
2390 return 'Bad entry in WATCHLISTS dict: %s' % result
2391
2392 if wd_key.s != w_key.s:
2393 return mismatch_template % (
2394 '%s at line %d' % (wd_key.s, wd_key.lineno),
2395 '%s at line %d' % (w_key.s, w_key.lineno))
2396
2397 if wd_key.s < last_key:
2398 return (
2399 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2400 (wd_key.lineno, w_key.lineno))
2401 last_key = wd_key.s
2402
2403 i = i + 1
2404
2405
2406def _CheckWATCHLISTSSyntax(expression, ast):
2407 if not isinstance(expression, ast.Expression):
2408 return 'WATCHLISTS file must contain a valid expression'
2409 dictionary = expression.body
2410 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2411 return 'WATCHLISTS file must have single dict with exactly two entries'
2412
2413 first_key = dictionary.keys[0]
2414 first_value = dictionary.values[0]
2415 second_key = dictionary.keys[1]
2416 second_value = dictionary.values[1]
2417
2418 if (not isinstance(first_key, ast.Str) or
2419 first_key.s != 'WATCHLIST_DEFINITIONS' or
2420 not isinstance(first_value, ast.Dict)):
2421 return (
2422 'The first entry of the dict in WATCHLISTS file must be '
2423 'WATCHLIST_DEFINITIONS dict')
2424
2425 if (not isinstance(second_key, ast.Str) or
2426 second_key.s != 'WATCHLISTS' or
2427 not isinstance(second_value, ast.Dict)):
2428 return (
2429 'The second entry of the dict in WATCHLISTS file must be '
2430 'WATCHLISTS dict')
2431
2432 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132433
2434
2435def _CheckWATCHLISTS(input_api, output_api):
2436 for f in input_api.AffectedFiles(include_deletes=False):
2437 if f.LocalPath() == 'WATCHLISTS':
2438 contents = input_api.ReadFile(f, 'r')
2439
2440 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202441 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132442 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202443 # Get an AST tree for it and scan the tree for detailed style checking.
2444 expression = input_api.ast.parse(
2445 contents, filename='WATCHLISTS', mode='eval')
2446 except ValueError as e:
2447 return [output_api.PresubmitError(
2448 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2449 except SyntaxError as e:
2450 return [output_api.PresubmitError(
2451 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2452 except TypeError as e:
2453 return [output_api.PresubmitError(
2454 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132455
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202456 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2457 if result is not None:
2458 return [output_api.PresubmitError(result)]
2459 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132460
2461 return []
2462
2463
dgnaa68d5e2015-06-10 10:08:222464def _AndroidSpecificOnUploadChecks(input_api, output_api):
2465 """Groups checks that target android code."""
2466 results = []
dgnaa68d5e2015-06-10 10:08:222467 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222468 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292469 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062470 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2471 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422472 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182473 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222474 return results
2475
2476
[email protected]22c9bd72011-03-27 16:47:392477def _CommonChecks(input_api, output_api):
2478 """Checks common to both upload and commit."""
2479 results = []
2480 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382481 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542482 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582483 results.extend(
2484 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192485 results.extend(
[email protected]760deea2013-12-10 19:33:492486 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542487 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182488 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522489 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222490 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442491 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592492 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062493 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122494 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182495 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222496 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302497 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492498 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032499 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492500 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442501 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272502 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072503 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542504 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442505 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392506 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552507 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042508 results.extend(
2509 input_api.canned_checks.CheckChangeHasNoTabs(
2510 input_api,
2511 output_api,
2512 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402513 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162514 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082515 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242516 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2517 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472518 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042519 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232520 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432521 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402522 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152523 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172524 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502525 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242526 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362527 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132528 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432529 results.extend(input_api.RunTests(
2530 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242531
2532 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2533 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2534 input_api, output_api,
2535 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382536 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392537 return results
[email protected]1f7b4172010-01-28 01:17:342538
[email protected]b337cb5b2011-01-23 21:24:052539
[email protected]b8079ae4a2012-12-05 19:56:492540def _CheckPatchFiles(input_api, output_api):
2541 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2542 if f.LocalPath().endswith(('.orig', '.rej'))]
2543 if problems:
2544 return [output_api.PresubmitError(
2545 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032546 else:
2547 return []
[email protected]b8079ae4a2012-12-05 19:56:492548
2549
Kent Tamura5a8755d2017-06-29 23:37:072550def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212551 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2552 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2553 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072554 include_re = input_api.re.compile(
2555 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2556 extension_re = input_api.re.compile(r'\.[a-z]+$')
2557 errors = []
2558 for f in input_api.AffectedFiles():
2559 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2560 continue
2561 found_line_number = None
2562 found_macro = None
2563 for line_num, line in f.ChangedContents():
2564 match = macro_re.search(line)
2565 if match:
2566 found_line_number = line_num
2567 found_macro = match.group(2)
2568 break
2569 if not found_line_number:
2570 continue
2571
2572 found_include = False
2573 for line in f.NewContents():
2574 if include_re.search(line):
2575 found_include = True
2576 break
2577 if found_include:
2578 continue
2579
2580 if not f.LocalPath().endswith('.h'):
2581 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2582 try:
2583 content = input_api.ReadFile(primary_header_path, 'r')
2584 if include_re.search(content):
2585 continue
2586 except IOError:
2587 pass
2588 errors.append('%s:%d %s macro is used without including build/'
2589 'build_config.h.'
2590 % (f.LocalPath(), found_line_number, found_macro))
2591 if errors:
2592 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2593 return []
2594
2595
[email protected]b00342e7f2013-03-26 16:21:542596def _DidYouMeanOSMacro(bad_macro):
2597 try:
2598 return {'A': 'OS_ANDROID',
2599 'B': 'OS_BSD',
2600 'C': 'OS_CHROMEOS',
2601 'F': 'OS_FREEBSD',
2602 'L': 'OS_LINUX',
2603 'M': 'OS_MACOSX',
2604 'N': 'OS_NACL',
2605 'O': 'OS_OPENBSD',
2606 'P': 'OS_POSIX',
2607 'S': 'OS_SOLARIS',
2608 'W': 'OS_WIN'}[bad_macro[3].upper()]
2609 except KeyError:
2610 return ''
2611
2612
2613def _CheckForInvalidOSMacrosInFile(input_api, f):
2614 """Check for sensible looking, totally invalid OS macros."""
2615 preprocessor_statement = input_api.re.compile(r'^\s*#')
2616 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2617 results = []
2618 for lnum, line in f.ChangedContents():
2619 if preprocessor_statement.search(line):
2620 for match in os_macro.finditer(line):
2621 if not match.group(1) in _VALID_OS_MACROS:
2622 good = _DidYouMeanOSMacro(match.group(1))
2623 did_you_mean = ' (did you mean %s?)' % good if good else ''
2624 results.append(' %s:%d %s%s' % (f.LocalPath(),
2625 lnum,
2626 match.group(1),
2627 did_you_mean))
2628 return results
2629
2630
2631def _CheckForInvalidOSMacros(input_api, output_api):
2632 """Check all affected files for invalid OS macros."""
2633 bad_macros = []
2634 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472635 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542636 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2637
2638 if not bad_macros:
2639 return []
2640
2641 return [output_api.PresubmitError(
2642 'Possibly invalid OS macro[s] found. Please fix your code\n'
2643 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2644
lliabraa35bab3932014-10-01 12:16:442645
2646def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2647 """Check all affected files for invalid "if defined" macros."""
2648 ALWAYS_DEFINED_MACROS = (
2649 "TARGET_CPU_PPC",
2650 "TARGET_CPU_PPC64",
2651 "TARGET_CPU_68K",
2652 "TARGET_CPU_X86",
2653 "TARGET_CPU_ARM",
2654 "TARGET_CPU_MIPS",
2655 "TARGET_CPU_SPARC",
2656 "TARGET_CPU_ALPHA",
2657 "TARGET_IPHONE_SIMULATOR",
2658 "TARGET_OS_EMBEDDED",
2659 "TARGET_OS_IPHONE",
2660 "TARGET_OS_MAC",
2661 "TARGET_OS_UNIX",
2662 "TARGET_OS_WIN32",
2663 )
2664 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2665 results = []
2666 for lnum, line in f.ChangedContents():
2667 for match in ifdef_macro.finditer(line):
2668 if match.group(1) in ALWAYS_DEFINED_MACROS:
2669 always_defined = ' %s is always defined. ' % match.group(1)
2670 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2671 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2672 lnum,
2673 always_defined,
2674 did_you_mean))
2675 return results
2676
2677
2678def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2679 """Check all affected files for invalid "if defined" macros."""
2680 bad_macros = []
2681 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212682 if f.LocalPath().startswith('third_party/sqlite/'):
2683 continue
lliabraa35bab3932014-10-01 12:16:442684 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2685 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2686
2687 if not bad_macros:
2688 return []
2689
2690 return [output_api.PresubmitError(
2691 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2692 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2693 bad_macros)]
2694
2695
mlamouria82272622014-09-16 18:45:042696def _CheckForIPCRules(input_api, output_api):
2697 """Check for same IPC rules described in
2698 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2699 """
2700 base_pattern = r'IPC_ENUM_TRAITS\('
2701 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2702 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2703
2704 problems = []
2705 for f in input_api.AffectedSourceFiles(None):
2706 local_path = f.LocalPath()
2707 if not local_path.endswith('.h'):
2708 continue
2709 for line_number, line in f.ChangedContents():
2710 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2711 problems.append(
2712 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2713
2714 if problems:
2715 return [output_api.PresubmitPromptWarning(
2716 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2717 else:
2718 return []
2719
[email protected]b00342e7f2013-03-26 16:21:542720
mostynbb639aca52015-01-07 20:31:232721def _CheckForWindowsLineEndings(input_api, output_api):
2722 """Check source code and known ascii text files for Windows style line
2723 endings.
2724 """
earthdok1b5e0ee2015-03-10 15:19:102725 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232726
2727 file_inclusion_pattern = (
2728 known_text_files,
2729 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2730 )
2731
mostynbb639aca52015-01-07 20:31:232732 problems = []
Andrew Grieve933d12e2017-10-30 20:22:532733 source_file_filter = lambda f: input_api.FilterSourceFile(
2734 f, white_list=file_inclusion_pattern, black_list=None)
2735 for f in input_api.AffectedSourceFiles(source_file_filter):
2736 for line_number, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:232737 if line.endswith('\r\n'):
Andrew Grieve933d12e2017-10-30 20:22:532738 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:232739
2740 if problems:
2741 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2742 'these files to contain Windows style line endings?\n' +
2743 '\n'.join(problems))]
2744
2745 return []
2746
2747
pastarmovj89f7ee12016-09-20 14:58:132748def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2749 lint_filters=None, verbose_level=None):
2750 """Checks that all source files use SYSLOG properly."""
2751 syslog_files = []
2752 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562753 for line_number, line in f.ChangedContents():
2754 if 'SYSLOG' in line:
2755 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2756
pastarmovj89f7ee12016-09-20 14:58:132757 if syslog_files:
2758 return [output_api.PresubmitPromptWarning(
2759 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2760 ' calls.\nFiles to check:\n', items=syslog_files)]
2761 return []
2762
2763
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192764def _CheckCrbugLinksHaveHttps(input_api, output_api):
Miguel Casas68bdb652017-12-19 16:29:092765 """Checks that crbug(.com) links are correctly prefixed by https://,
2766 unless they come in the accepted form TODO(crbug.com/...)
2767 """
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192768 white_list = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2769 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS)
2770 sources = lambda f: input_api.FilterSourceFile(
2771 f, white_list=white_list, black_list=black_list)
2772
2773 pattern = input_api.re.compile(r'//.*(?<!:\/\/)crbug[.com]*')
Miguel Casas68bdb652017-12-19 16:29:092774 accepted_pattern = input_api.re.compile(r'//.*TODO\(crbug[.com]*');
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192775 problems = []
2776 for f in input_api.AffectedSourceFiles(sources):
2777 for line_num, line in f.ChangedContents():
Miguel Casas68bdb652017-12-19 16:29:092778 if pattern.search(line) and not accepted_pattern.search(line):
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192779 problems.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2780
2781 if problems:
2782 return [output_api.PresubmitPromptWarning(
2783 'Found unprefixed crbug.com URL(s), consider prepending https://\n'+
2784 '\n'.join(problems))]
2785 return []
2786
2787
[email protected]1f7b4172010-01-28 01:17:342788def CheckChangeOnUpload(input_api, output_api):
2789 results = []
2790 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472791 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282792 results.extend(
jam93a6ee792017-02-08 23:59:222793 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192794 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222795 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132796 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162797 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192798 results.extend(_CheckCrbugLinksHaveHttps(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542799 return results
[email protected]ca8d1982009-02-19 16:33:122800
2801
[email protected]1bfb8322014-04-23 01:02:412802def GetTryServerMasterForBot(bot):
2803 """Returns the Try Server master for the given bot.
2804
[email protected]0bb112362014-07-26 04:38:322805 It tries to guess the master from the bot name, but may still fail
2806 and return None. There is no longer a default master.
2807 """
2808 # Potentially ambiguous bot names are listed explicitly.
2809 master_map = {
tandriie5587792016-07-14 00:34:502810 'chromium_presubmit': 'master.tryserver.chromium.linux',
2811 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412812 }
[email protected]0bb112362014-07-26 04:38:322813 master = master_map.get(bot)
2814 if not master:
wnwen4fbaab82016-05-25 12:54:362815 if 'android' in bot:
tandriie5587792016-07-14 00:34:502816 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362817 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502818 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322819 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502820 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322821 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502822 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322823 return master
[email protected]1bfb8322014-04-23 01:02:412824
2825
[email protected]ca8d1982009-02-19 16:33:122826def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542827 results = []
[email protected]1f7b4172010-01-28 01:17:342828 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542829 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272830 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342831 input_api,
2832 output_api,
[email protected]2fdd1f362013-01-16 03:56:032833 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272834
jam93a6ee792017-02-08 23:59:222835 results.extend(
2836 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542837 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2838 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412839 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2840 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542841 return results