blob: b5f115dbc99454f53fed795a829d9adabcc37dfa [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,
Steven Holte27008b7422018-01-29 20:55:4444 r'.+_(api|browser|eg|int|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
Sylvain Defresnea8b73d252018-02-28 15:45:54182_BANNED_IOS_OBJC_FUNCTIONS = (
183 (
184 r'/\bTEST[(]',
185 (
186 'TEST() macro should not be used in Objective-C++ code as it does not ',
187 'drain the autorelease pool at the end of the test. Use TEST_F() ',
188 'macro instead with a fixture inheriting from PlatformTest (or a ',
189 'typedef).'
190 ),
191 True,
192 ),
193 (
194 r'/\btesting::Test\b',
195 (
196 'testing::Test should not be used in Objective-C++ code as it does ',
197 'not drain the autorelease pool at the end of the test. Use ',
198 'PlatformTest instead.'
199 ),
200 True,
201 ),
202)
203
[email protected]127f18ec2012-06-16 05:05:59204
205_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20206 # Make sure that gtest's FRIEND_TEST() macro is not used; the
207 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30208 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20209 (
thomasandersone7caaa9b2017-03-29 19:22:53210 r'\bNULL\b',
211 (
212 'New code should not use NULL. Use nullptr instead.',
213 ),
214 True,
215 (),
216 ),
217 (
[email protected]23e6cbc2012-06-16 18:51:20218 'FRIEND_TEST(',
219 (
[email protected]e3c945502012-06-26 20:01:49220 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20221 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
222 ),
223 False,
[email protected]7345da02012-11-27 14:31:49224 (),
[email protected]23e6cbc2012-06-16 18:51:20225 ),
226 (
thomasanderson4b569052016-09-14 20:15:53227 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
228 (
229 'Chrome clients wishing to select events on X windows should use',
230 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
231 'you are selecting events from the GPU process, or if you are using',
232 'an XDisplay other than gfx::GetXDisplay().',
233 ),
234 True,
235 (
236 r"^ui[\\\/]gl[\\\/].*\.cc$",
237 r"^media[\\\/]gpu[\\\/].*\.cc$",
238 r"^gpu[\\\/].*\.cc$",
239 ),
240 ),
241 (
thomasandersone043e3ce2017-06-08 00:43:20242 r'XInternAtom|xcb_intern_atom',
243 (
thomasanderson11aa41dc2017-06-08 22:22:38244 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20245 ),
246 True,
247 (
thomasanderson11aa41dc2017-06-08 22:22:38248 r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$",
249 r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20250 r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$",
251 ),
252 ),
253 (
tomhudsone2c14d552016-05-26 17:07:46254 'setMatrixClip',
255 (
256 'Overriding setMatrixClip() is prohibited; ',
257 'the base function is deprecated. ',
258 ),
259 True,
260 (),
261 ),
262 (
[email protected]52657f62013-05-20 05:30:31263 'SkRefPtr',
264 (
265 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22266 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31267 ),
268 True,
269 (),
270 ),
271 (
272 'SkAutoRef',
273 (
274 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22275 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31276 ),
277 True,
278 (),
279 ),
280 (
281 'SkAutoTUnref',
282 (
283 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22284 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31285 ),
286 True,
287 (),
288 ),
289 (
290 'SkAutoUnref',
291 (
292 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
293 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22294 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31295 ),
296 True,
297 (),
298 ),
[email protected]d89eec82013-12-03 14:10:59299 (
300 r'/HANDLE_EINTR\(.*close',
301 (
302 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
303 'descriptor will be closed, and it is incorrect to retry the close.',
304 'Either call close directly and ignore its return value, or wrap close',
305 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
306 ),
307 True,
308 (),
309 ),
310 (
311 r'/IGNORE_EINTR\((?!.*close)',
312 (
313 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
314 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
315 ),
316 True,
317 (
318 # Files that #define IGNORE_EINTR.
319 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
320 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
321 ),
322 ),
[email protected]ec5b3f02014-04-04 18:43:43323 (
324 r'/v8::Extension\(',
325 (
326 'Do not introduce new v8::Extensions into the code base, use',
327 'gin::Wrappable instead. See http://crbug.com/334679',
328 ),
329 True,
[email protected]f55c90ee62014-04-12 00:50:03330 (
joaodasilva718f87672014-08-30 09:25:49331 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03332 ),
[email protected]ec5b3f02014-04-04 18:43:43333 ),
skyostilf9469f72015-04-20 10:38:52334 (
jame2d1a952016-04-02 00:27:10335 '#pragma comment(lib,',
336 (
337 'Specify libraries to link with in build files and not in the source.',
338 ),
339 True,
340 (),
341 ),
fdorayc4ac18d2017-05-01 21:39:59342 (
gabd52c912a2017-05-11 04:15:59343 'base::SequenceChecker',
344 (
345 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
346 ),
347 False,
348 (),
349 ),
350 (
351 'base::ThreadChecker',
352 (
353 'Consider using THREAD_CHECKER macros instead of the class directly.',
354 ),
355 False,
356 (),
357 ),
dbeamb6f4fde2017-06-15 04:03:06358 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06359 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
360 (
361 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
362 'deprecated (http://crbug.com/634507). Please avoid converting away',
363 'from the Time types in Chromium code, especially if any math is',
364 'being done on time values. For interfacing with platform/library',
365 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
366 'type converter methods instead. For faking TimeXXX values (for unit',
367 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
368 'other use cases, please contact base/time/OWNERS.',
369 ),
370 False,
371 (),
372 ),
373 (
dbeamb6f4fde2017-06-15 04:03:06374 'CallJavascriptFunctionUnsafe',
375 (
376 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
377 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
378 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
379 ),
380 False,
381 (
382 r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$',
383 r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$',
384 r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$',
385 ),
386 ),
dskiba1474c2bfd62017-07-20 02:19:24387 (
388 'leveldb::DB::Open',
389 (
390 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
391 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
392 "Chrome's tracing, making their memory usage visible.",
393 ),
394 True,
395 (
396 r'^third_party/leveldatabase/.*\.(cc|h)$',
397 ),
Gabriel Charette0592c3a2017-07-26 12:02:04398 ),
399 (
Chris Mumfordc38afb62017-10-09 17:55:08400 'leveldb::NewMemEnv',
401 (
402 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
403 'third_party/leveldatabase/leveldb_chrome.h.',
404 ),
405 True,
406 (
407 r'^third_party/leveldatabase/.*\.(cc|h)$',
408 ),
409 ),
410 (
Gabriel Charetted9839bc2017-07-29 14:17:47411 'MessageLoop::QuitWhenIdleClosure',
Gabriel Charette0592c3a2017-07-26 12:02:04412 (
Peter Kasting9e7ccfa52018-02-06 00:01:20413 'MessageLoop::QuitWhenIdleClosure is deprecated. Please use a',
414 'QuitWhenIdleClosure obtained from a specific RunLoop instance.',
Gabriel Charette0592c3a2017-07-26 12:02:04415 ),
Peter Kasting9e7ccfa52018-02-06 00:01:20416 False,
Gabriel Charette0592c3a2017-07-26 12:02:04417 (),
Gabriel Charetted9839bc2017-07-29 14:17:47418 ),
419 (
420 'RunLoop::QuitCurrent',
421 (
Robert Liao64b7ab22017-08-04 23:03:43422 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
423 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47424 ),
425 True,
426 (),
Gabriel Charettea44975052017-08-21 23:14:04427 ),
428 (
429 'base::ScopedMockTimeMessageLoopTaskRunner',
430 (
431 'ScopedMockTimeMessageLoopTaskRunner is deprecated.',
432 ),
433 True,
434 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57435 ),
436 (
437 r'std::regex',
438 (
439 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02440 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57441 ),
442 True,
443 (),
Francois Doray43670e32017-09-27 12:40:38444 ),
445 (
446 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
447 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
448 (
449 'Use the new API in base/threading/thread_restrictions.h.',
450 ),
451 True,
452 (),
453 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38454 (
455 r'/\bbase::Bind\(',
456 (
457 'Please consider using base::Bind{Once,Repeating} instead '
Mostyn Bramley-Moore6b427322017-12-21 22:11:02458 'of base::Bind. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38459 ),
460 False,
461 (),
462 ),
463 (
464 r'/\bbase::Callback<',
465 (
466 'Please consider using base::{Once,Repeating}Callback instead '
Mostyn Bramley-Moore6b427322017-12-21 22:11:02467 'of base::Callback. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38468 ),
469 False,
470 (),
471 ),
472 (
473 r'/\bbase::Closure\b',
474 (
475 'Please consider using base::{Once,Repeating}Closure instead '
Mostyn Bramley-Moore6b427322017-12-21 22:11:02476 'of base::Closure. (crbug.com/714018)',
Luis Hector Chavez9bbaed532017-11-30 18:25:38477 ),
478 False,
479 (),
480 ),
Victor Costan3653df62018-02-08 21:38:16481 (
482 'sqlite3_initialize',
483 (
484 'Instead of sqlite3_initialize, depend on //sql, ',
485 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
486 ),
487 True,
488 (
489 r'^sql/initialization\.(cc|h)$',
490 r'^third_party/sqlite/.*\.(c|cc|h)$',
491 ),
492 ),
[email protected]127f18ec2012-06-16 05:05:59493)
494
wnwenbdc444e2016-05-25 13:44:15495
mlamouria82272622014-09-16 18:45:04496_IPC_ENUM_TRAITS_DEPRECATED = (
497 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
498 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
499
Shenghua Zhangbfaa38b82017-11-16 21:58:02500_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
501 r".*[\\\/]BuildHooksAndroidImpl\.java",
502 r".*[\\\/]LicenseContentProvider\.java",
503]
[email protected]127f18ec2012-06-16 05:05:59504
Sean Kau46e29bc2017-08-28 16:31:16505# These paths contain test data and other known invalid JSON files.
506_KNOWN_INVALID_JSON_FILE_PATTERNS = [
507 r'test[\\\/]data[\\\/]',
508 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
509 r'^third_party[\\\/]protobuf[\\\/]',
Raphael Kubo da Costa211f3b472017-11-16 00:27:16510 r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]',
Sean Kau46e29bc2017-08-28 16:31:16511]
512
513
[email protected]b00342e7f2013-03-26 16:21:54514_VALID_OS_MACROS = (
515 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08516 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54517 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:12518 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:54519 'OS_BSD',
520 'OS_CAT', # For testing.
521 'OS_CHROMEOS',
522 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37523 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54524 'OS_IOS',
525 'OS_LINUX',
526 'OS_MACOSX',
527 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21528 'OS_NACL_NONSFI',
529 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12530 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54531 'OS_OPENBSD',
532 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37533 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54534 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54535 'OS_WIN',
536)
537
538
agrievef32bcc72016-04-04 14:57:40539_ANDROID_SPECIFIC_PYDEPS_FILES = [
540 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04541 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58542 'build/secondary/third_party/android_platform/'
543 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19544 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40545]
546
wnwenbdc444e2016-05-25 13:44:15547
agrievef32bcc72016-04-04 14:57:40548_GENERIC_PYDEPS_FILES = [
John Chencde89192018-01-27 21:18:40549 'chrome/test/chromedriver/test/run_py_tests.pydeps',
agrievef32bcc72016-04-04 14:57:40550]
551
wnwenbdc444e2016-05-25 13:44:15552
agrievef32bcc72016-04-04 14:57:40553_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
554
555
Eric Boren6fd2b932018-01-25 15:05:08556# Bypass the AUTHORS check for these accounts.
557_KNOWN_ROBOTS = set(
558 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
Eric Borenf7f08f02018-02-08 20:22:52559 for s in ('afdo', 'angle', 'catapult', 'depot-tools', 'nacl', 'pdfium',
560 'skia', 'src-internal', 'webrtc'))
Eric Boren6fd2b932018-01-25 15:05:08561
562
[email protected]55459852011-08-10 15:17:19563def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
564 """Attempts to prevent use of functions intended only for testing in
565 non-testing code. For now this is just a best-effort implementation
566 that ignores header files and may have some false positives. A
567 better implementation would probably need a proper C++ parser.
568 """
569 # We only scan .cc files and the like, as the declaration of
570 # for-testing functions in header files are hard to distinguish from
571 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44572 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19573
jochenc0d4808c2015-07-27 09:25:42574 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19575 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09576 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19577 exclusion_pattern = input_api.re.compile(
578 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
579 base_function_pattern, base_function_pattern))
580
581 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44582 black_list = (_EXCLUDED_PATHS +
583 _TEST_CODE_EXCLUDED_PATHS +
584 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19585 return input_api.FilterSourceFile(
586 affected_file,
587 white_list=(file_inclusion_pattern, ),
588 black_list=black_list)
589
590 problems = []
591 for f in input_api.AffectedSourceFiles(FilterFile):
592 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24593 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03594 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46595 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03596 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19597 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03598 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19599
600 if problems:
[email protected]f7051d52013-04-02 18:31:42601 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03602 else:
603 return []
[email protected]55459852011-08-10 15:17:19604
605
[email protected]10689ca2011-09-02 02:31:54606def _CheckNoIOStreamInHeaders(input_api, output_api):
607 """Checks to make sure no .h files include <iostream>."""
608 files = []
609 pattern = input_api.re.compile(r'^#include\s*<iostream>',
610 input_api.re.MULTILINE)
611 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
612 if not f.LocalPath().endswith('.h'):
613 continue
614 contents = input_api.ReadFile(f)
615 if pattern.search(contents):
616 files.append(f)
617
618 if len(files):
yolandyandaabc6d2016-04-18 18:29:39619 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06620 'Do not #include <iostream> in header files, since it inserts static '
621 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54622 '#include <ostream>. See http://crbug.com/94794',
623 files) ]
624 return []
625
626
[email protected]72df4e782012-06-21 16:28:18627def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52628 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18629 problems = []
630 for f in input_api.AffectedFiles():
631 if (not f.LocalPath().endswith(('.cc', '.mm'))):
632 continue
633
634 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04635 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18636 problems.append(' %s:%d' % (f.LocalPath(), line_num))
637
638 if not problems:
639 return []
640 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
641 '\n'.join(problems))]
642
643
danakj61c1aa22015-10-26 19:55:52644def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57645 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52646 errors = []
647 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
648 input_api.re.MULTILINE)
649 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
650 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
651 continue
652 for lnum, line in f.ChangedContents():
653 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17654 errors.append(output_api.PresubmitError(
655 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57656 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17657 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52658 return errors
659
660
mcasasb7440c282015-02-04 14:52:19661def _FindHistogramNameInLine(histogram_name, line):
662 """Tries to find a histogram name or prefix in a line."""
663 if not "affected-histogram" in line:
664 return histogram_name in line
665 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
666 # the histogram_name.
667 if not '"' in line:
668 return False
669 histogram_prefix = line.split('\"')[1]
670 return histogram_prefix in histogram_name
671
672
673def _CheckUmaHistogramChanges(input_api, output_api):
674 """Check that UMA histogram names in touched lines can still be found in other
675 lines of the patch or in histograms.xml. Note that this check would not catch
676 the reverse: changes in histograms.xml not matched in the code itself."""
677 touched_histograms = []
678 histograms_xml_modifications = []
679 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
680 for f in input_api.AffectedFiles():
681 # If histograms.xml itself is modified, keep the modified lines for later.
682 if f.LocalPath().endswith(('histograms.xml')):
683 histograms_xml_modifications = f.ChangedContents()
684 continue
685 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
686 continue
687 for line_num, line in f.ChangedContents():
688 found = pattern.search(line)
689 if found:
690 touched_histograms.append([found.group(1), f, line_num])
691
692 # Search for the touched histogram names in the local modifications to
693 # histograms.xml, and, if not found, on the base histograms.xml file.
694 unmatched_histograms = []
695 for histogram_info in touched_histograms:
696 histogram_name_found = False
697 for line_num, line in histograms_xml_modifications:
698 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
699 if histogram_name_found:
700 break
701 if not histogram_name_found:
702 unmatched_histograms.append(histogram_info)
703
eromanb90c82e7e32015-04-01 15:13:49704 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19705 problems = []
706 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49707 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19708 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45709 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19710 histogram_name_found = False
711 for line in histograms_xml:
712 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
713 if histogram_name_found:
714 break
715 if not histogram_name_found:
716 problems.append(' [%s:%d] %s' %
717 (f.LocalPath(), line_num, histogram_name))
718
719 if not problems:
720 return []
721 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
722 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49723 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19724
wnwenbdc444e2016-05-25 13:44:15725
yolandyandaabc6d2016-04-18 18:29:39726def _CheckFlakyTestUsage(input_api, output_api):
727 """Check that FlakyTest annotation is our own instead of the android one"""
728 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
729 files = []
730 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
731 if f.LocalPath().endswith('Test.java'):
732 if pattern.search(input_api.ReadFile(f)):
733 files.append(f)
734 if len(files):
735 return [output_api.PresubmitError(
736 'Use org.chromium.base.test.util.FlakyTest instead of '
737 'android.test.FlakyTest',
738 files)]
739 return []
mcasasb7440c282015-02-04 14:52:19740
wnwenbdc444e2016-05-25 13:44:15741
[email protected]8ea5d4b2011-09-13 21:49:22742def _CheckNoNewWStrings(input_api, output_api):
743 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27744 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22745 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20746 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57747 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34748 '/win/' in f.LocalPath() or
749 'chrome_elf' in f.LocalPath() or
750 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20751 continue
[email protected]8ea5d4b2011-09-13 21:49:22752
[email protected]a11dbe9b2012-08-07 01:32:58753 allowWString = False
[email protected]b5c24292011-11-28 14:38:20754 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58755 if 'presubmit: allow wstring' in line:
756 allowWString = True
757 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27758 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58759 allowWString = False
760 else:
761 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22762
[email protected]55463aa62011-10-12 00:48:27763 if not problems:
764 return []
765 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58766 ' If you are calling a cross-platform API that accepts a wstring, '
767 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27768 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22769
770
[email protected]2a8ac9c2011-10-19 17:20:44771def _CheckNoDEPSGIT(input_api, output_api):
772 """Make sure .DEPS.git is never modified manually."""
773 if any(f.LocalPath().endswith('.DEPS.git') for f in
774 input_api.AffectedFiles()):
775 return [output_api.PresubmitError(
776 'Never commit changes to .DEPS.git. This file is maintained by an\n'
777 'automated system based on what\'s in DEPS and your changes will be\n'
778 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34779 '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:44780 'for more information')]
781 return []
782
783
tandriief664692014-09-23 14:51:47784def _CheckValidHostsInDEPS(input_api, output_api):
785 """Checks that DEPS file deps are from allowed_hosts."""
786 # Run only if DEPS file has been modified to annoy fewer bystanders.
787 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
788 return []
789 # Outsource work to gclient verify
790 try:
791 input_api.subprocess.check_output(['gclient', 'verify'])
792 return []
793 except input_api.subprocess.CalledProcessError, error:
794 return [output_api.PresubmitError(
795 'DEPS file must have only git dependencies.',
796 long_text=error.output)]
797
798
[email protected]127f18ec2012-06-16 05:05:59799def _CheckNoBannedFunctions(input_api, output_api):
800 """Make sure that banned functions are not used."""
801 warnings = []
802 errors = []
803
wnwenbdc444e2016-05-25 13:44:15804 def IsBlacklisted(affected_file, blacklist):
805 local_path = affected_file.LocalPath()
806 for item in blacklist:
807 if input_api.re.match(item, local_path):
808 return True
809 return False
810
Sylvain Defresnea8b73d252018-02-28 15:45:54811 def IsIosObcjFile(affected_file):
812 local_path = affected_file.LocalPath()
813 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
814 return False
815 basename = input_api.os_path.basename(local_path)
816 if 'ios' in basename.split('_'):
817 return True
818 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
819 if sep and 'ios' in local_path.split(sep):
820 return True
821 return False
822
wnwenbdc444e2016-05-25 13:44:15823 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
824 matched = False
825 if func_name[0:1] == '/':
826 regex = func_name[1:]
827 if input_api.re.search(regex, line):
828 matched = True
829 elif func_name in line:
dchenge07de812016-06-20 19:27:17830 matched = True
wnwenbdc444e2016-05-25 13:44:15831 if matched:
dchenge07de812016-06-20 19:27:17832 problems = warnings
wnwenbdc444e2016-05-25 13:44:15833 if error:
dchenge07de812016-06-20 19:27:17834 problems = errors
wnwenbdc444e2016-05-25 13:44:15835 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
836 for message_line in message:
837 problems.append(' %s' % message_line)
838
Eric Stevensona9a980972017-09-23 00:04:41839 file_filter = lambda f: f.LocalPath().endswith(('.java'))
840 for f in input_api.AffectedFiles(file_filter=file_filter):
841 for line_num, line in f.ChangedContents():
842 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
843 CheckForMatch(f, line_num, line, func_name, message, error)
844
[email protected]127f18ec2012-06-16 05:05:59845 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
846 for f in input_api.AffectedFiles(file_filter=file_filter):
847 for line_num, line in f.ChangedContents():
848 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15849 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59850
Sylvain Defresnea8b73d252018-02-28 15:45:54851 for f in input_api.AffectedFiles(file_filter=IsIosObcjFile):
852 for line_num, line in f.ChangedContents():
853 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
854 CheckForMatch(f, line_num, line, func_name, message, error)
855
[email protected]127f18ec2012-06-16 05:05:59856 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
857 for f in input_api.AffectedFiles(file_filter=file_filter):
858 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49859 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49860 if IsBlacklisted(f, excluded_paths):
861 continue
wnwenbdc444e2016-05-25 13:44:15862 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59863
864 result = []
865 if (warnings):
866 result.append(output_api.PresubmitPromptWarning(
867 'Banned functions were used.\n' + '\n'.join(warnings)))
868 if (errors):
869 result.append(output_api.PresubmitError(
870 'Banned functions were used.\n' + '\n'.join(errors)))
871 return result
872
873
[email protected]6c063c62012-07-11 19:11:06874def _CheckNoPragmaOnce(input_api, output_api):
875 """Make sure that banned functions are not used."""
876 files = []
877 pattern = input_api.re.compile(r'^#pragma\s+once',
878 input_api.re.MULTILINE)
879 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
880 if not f.LocalPath().endswith('.h'):
881 continue
882 contents = input_api.ReadFile(f)
883 if pattern.search(contents):
884 files.append(f)
885
886 if files:
887 return [output_api.PresubmitError(
888 'Do not use #pragma once in header files.\n'
889 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
890 files)]
891 return []
892
[email protected]127f18ec2012-06-16 05:05:59893
[email protected]e7479052012-09-19 00:26:12894def _CheckNoTrinaryTrueFalse(input_api, output_api):
895 """Checks to make sure we don't introduce use of foo ? true : false."""
896 problems = []
897 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
898 for f in input_api.AffectedFiles():
899 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
900 continue
901
902 for line_num, line in f.ChangedContents():
903 if pattern.match(line):
904 problems.append(' %s:%d' % (f.LocalPath(), line_num))
905
906 if not problems:
907 return []
908 return [output_api.PresubmitPromptWarning(
909 'Please consider avoiding the "? true : false" pattern if possible.\n' +
910 '\n'.join(problems))]
911
912
[email protected]55f9f382012-07-31 11:02:18913def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28914 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18915 change. Breaking - rules is an error, breaking ! rules is a
916 warning.
917 """
mohan.reddyf21db962014-10-16 12:26:47918 import sys
[email protected]55f9f382012-07-31 11:02:18919 # We need to wait until we have an input_api object and use this
920 # roundabout construct to import checkdeps because this file is
921 # eval-ed and thus doesn't have __file__.
922 original_sys_path = sys.path
923 try:
924 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47925 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18926 import checkdeps
927 from cpp_checker import CppChecker
Jinsuk Kim5a092672017-10-24 22:42:24928 from java_checker import JavaChecker
rhalavati08acd232017-04-03 07:23:28929 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18930 from rules import Rule
931 finally:
932 # Restore sys.path to what it was before.
933 sys.path = original_sys_path
934
935 added_includes = []
rhalavati08acd232017-04-03 07:23:28936 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:24937 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:18938 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28939 if CppChecker.IsCppFile(f.LocalPath()):
940 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08941 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
rhalavati08acd232017-04-03 07:23:28942 elif ProtoChecker.IsProtoFile(f.LocalPath()):
943 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08944 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:24945 elif JavaChecker.IsJavaFile(f.LocalPath()):
946 changed_lines = [line for line_num, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:08947 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18948
[email protected]26385172013-05-09 23:11:35949 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18950
951 error_descriptions = []
952 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28953 error_subjects = set()
954 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18955 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
956 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:08957 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18958 description_with_path = '%s\n %s' % (path, rule_description)
959 if rule_type == Rule.DISALLOW:
960 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28961 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18962 else:
963 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28964 warning_subjects.add("#includes")
965
966 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
967 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:08968 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:28969 description_with_path = '%s\n %s' % (path, rule_description)
970 if rule_type == Rule.DISALLOW:
971 error_descriptions.append(description_with_path)
972 error_subjects.add("imports")
973 else:
974 warning_descriptions.append(description_with_path)
975 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18976
Jinsuk Kim5a092672017-10-24 22:42:24977 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:02978 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:08979 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:24980 description_with_path = '%s\n %s' % (path, rule_description)
981 if rule_type == Rule.DISALLOW:
982 error_descriptions.append(description_with_path)
983 error_subjects.add("imports")
984 else:
985 warning_descriptions.append(description_with_path)
986 warning_subjects.add("imports")
987
[email protected]55f9f382012-07-31 11:02:18988 results = []
989 if error_descriptions:
990 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28991 'You added one or more %s that violate checkdeps rules.'
992 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18993 error_descriptions))
994 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42995 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28996 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18997 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28998 '%s? See relevant DEPS file(s) for details and contacts.' %
999 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:181000 warning_descriptions))
1001 return results
1002
1003
[email protected]fbcafe5a2012-08-08 15:31:221004def _CheckFilePermissions(input_api, output_api):
1005 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:151006 if input_api.platform == 'win32':
1007 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:291008 checkperms_tool = input_api.os_path.join(
1009 input_api.PresubmitLocalPath(),
1010 'tools', 'checkperms', 'checkperms.py')
1011 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:471012 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:391013 with input_api.CreateTemporaryFile() as file_list:
1014 for f in input_api.AffectedFiles():
1015 # checkperms.py file/directory arguments must be relative to the
1016 # repository.
1017 file_list.write(f.LocalPath() + '\n')
1018 file_list.close()
1019 args += ['--file-list', file_list.name]
1020 try:
1021 input_api.subprocess.check_output(args)
1022 return []
1023 except input_api.subprocess.CalledProcessError as error:
1024 return [output_api.PresubmitError(
1025 'checkperms.py failed:',
1026 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:221027
1028
robertocn832f5992017-01-04 19:01:301029def _CheckTeamTags(input_api, output_api):
1030 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
1031 checkteamtags_tool = input_api.os_path.join(
1032 input_api.PresubmitLocalPath(),
1033 'tools', 'checkteamtags', 'checkteamtags.py')
1034 args = [input_api.python_executable, checkteamtags_tool,
1035 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:221036 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:301037 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
1038 'OWNERS']
1039 try:
1040 if files:
1041 input_api.subprocess.check_output(args + files)
1042 return []
1043 except input_api.subprocess.CalledProcessError as error:
1044 return [output_api.PresubmitError(
1045 'checkteamtags.py failed:',
1046 long_text=error.output)]
1047
1048
[email protected]c8278b32012-10-30 20:35:491049def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
1050 """Makes sure we don't include ui/aura/window_property.h
1051 in header files.
1052 """
1053 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1054 errors = []
1055 for f in input_api.AffectedFiles():
1056 if not f.LocalPath().endswith('.h'):
1057 continue
1058 for line_num, line in f.ChangedContents():
1059 if pattern.match(line):
1060 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1061
1062 results = []
1063 if errors:
1064 results.append(output_api.PresubmitError(
1065 'Header files should not include ui/aura/window_property.h', errors))
1066 return results
1067
1068
[email protected]70ca77752012-11-20 03:45:031069def _CheckForVersionControlConflictsInFile(input_api, f):
1070 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1071 errors = []
1072 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231073 if f.LocalPath().endswith('.md'):
1074 # First-level headers in markdown look a lot like version control
1075 # conflict markers. http://daringfireball.net/projects/markdown/basics
1076 continue
[email protected]70ca77752012-11-20 03:45:031077 if pattern.match(line):
1078 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1079 return errors
1080
1081
1082def _CheckForVersionControlConflicts(input_api, output_api):
1083 """Usually this is not intentional and will cause a compile failure."""
1084 errors = []
1085 for f in input_api.AffectedFiles():
1086 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1087
1088 results = []
1089 if errors:
1090 results.append(output_api.PresubmitError(
1091 'Version control conflict markers found, please resolve.', errors))
1092 return results
1093
estadee17314a02017-01-12 16:22:161094def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1095 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1096 errors = []
1097 for f in input_api.AffectedFiles():
1098 for line_num, line in f.ChangedContents():
1099 if pattern.search(line):
1100 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1101
1102 results = []
1103 if errors:
1104 results.append(output_api.PresubmitPromptWarning(
1105 'Found Google support URL addressed by answer number. Please replace with '
1106 'a p= identifier instead. See crbug.com/679462\n', errors))
1107 return results
1108
[email protected]70ca77752012-11-20 03:45:031109
[email protected]06e6d0ff2012-12-11 01:36:441110def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1111 def FilterFile(affected_file):
1112 """Filter function for use with input_api.AffectedSourceFiles,
1113 below. This filters out everything except non-test files from
1114 top-level directories that generally speaking should not hard-code
1115 service URLs (e.g. src/android_webview/, src/content/ and others).
1116 """
1117 return input_api.FilterSourceFile(
1118 affected_file,
[email protected]78bb39d62012-12-11 15:11:561119 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441120 black_list=(_EXCLUDED_PATHS +
1121 _TEST_CODE_EXCLUDED_PATHS +
1122 input_api.DEFAULT_BLACK_LIST))
1123
reillyi38965732015-11-16 18:27:331124 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1125 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461126 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1127 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441128 problems = [] # items are (filename, line_number, line)
1129 for f in input_api.AffectedSourceFiles(FilterFile):
1130 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461131 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441132 problems.append((f.LocalPath(), line_num, line))
1133
1134 if problems:
[email protected]f7051d52013-04-02 18:31:421135 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441136 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581137 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441138 [' %s:%d: %s' % (
1139 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031140 else:
1141 return []
[email protected]06e6d0ff2012-12-11 01:36:441142
1143
[email protected]d2530012013-01-25 16:39:271144def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1145 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311146 The native_client_sdk directory is excluded because it has auto-generated PNG
1147 files for documentation.
[email protected]d2530012013-01-25 16:39:271148 """
[email protected]d2530012013-01-25 16:39:271149 errors = []
binji0dcdf342014-12-12 18:32:311150 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1151 black_list = (r'^native_client_sdk[\\\/]',)
1152 file_filter = lambda f: input_api.FilterSourceFile(
1153 f, white_list=white_list, black_list=black_list)
1154 for f in input_api.AffectedFiles(include_deletes=False,
1155 file_filter=file_filter):
1156 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271157
1158 results = []
1159 if errors:
1160 results.append(output_api.PresubmitError(
1161 'The name of PNG files should not have abbreviations. \n'
1162 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1163 'Contact [email protected] if you have questions.', errors))
1164 return results
1165
1166
Daniel Cheng4dcdb6b2017-04-13 08:30:171167def _ExtractAddRulesFromParsedDeps(parsed_deps):
1168 """Extract the rules that add dependencies from a parsed DEPS file.
1169
1170 Args:
1171 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1172 add_rules = set()
1173 add_rules.update([
1174 rule[1:] for rule in parsed_deps.get('include_rules', [])
1175 if rule.startswith('+') or rule.startswith('!')
1176 ])
1177 for specific_file, rules in parsed_deps.get('specific_include_rules',
1178 {}).iteritems():
1179 add_rules.update([
1180 rule[1:] for rule in rules
1181 if rule.startswith('+') or rule.startswith('!')
1182 ])
1183 return add_rules
1184
1185
1186def _ParseDeps(contents):
1187 """Simple helper for parsing DEPS files."""
1188 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171189 class _VarImpl:
1190
1191 def __init__(self, local_scope):
1192 self._local_scope = local_scope
1193
1194 def Lookup(self, var_name):
1195 """Implements the Var syntax."""
1196 try:
1197 return self._local_scope['vars'][var_name]
1198 except KeyError:
1199 raise Exception('Var is not defined: %s' % var_name)
1200
1201 local_scope = {}
1202 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171203 'Var': _VarImpl(local_scope).Lookup,
1204 }
1205 exec contents in global_scope, local_scope
1206 return local_scope
1207
1208
1209def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081210 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411211 a set of DEPS entries that we should look up.
1212
1213 For a directory (rather than a specific filename) we fake a path to
1214 a specific filename by adding /DEPS. This is chosen as a file that
1215 will seldom or never be subject to per-file include_rules.
1216 """
[email protected]2b438d62013-11-14 17:54:141217 # We ignore deps entries on auto-generated directories.
1218 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081219
Daniel Cheng4dcdb6b2017-04-13 08:30:171220 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1221 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1222
1223 added_deps = new_deps.difference(old_deps)
1224
[email protected]2b438d62013-11-14 17:54:141225 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171226 for added_dep in added_deps:
1227 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1228 continue
1229 # Assume that a rule that ends in .h is a rule for a specific file.
1230 if added_dep.endswith('.h'):
1231 results.add(added_dep)
1232 else:
1233 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081234 return results
1235
1236
[email protected]e871964c2013-05-13 14:14:551237def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1238 """When a dependency prefixed with + is added to a DEPS file, we
1239 want to make sure that the change is reviewed by an OWNER of the
1240 target file or directory, to avoid layering violations from being
1241 introduced. This check verifies that this happens.
1242 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171243 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241244
1245 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191246 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241247 for f in input_api.AffectedFiles(include_deletes=False,
1248 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551249 filename = input_api.os_path.basename(f.LocalPath())
1250 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171251 virtual_depended_on_files.update(_CalculateAddedDeps(
1252 input_api.os_path,
1253 '\n'.join(f.OldContents()),
1254 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551255
[email protected]e871964c2013-05-13 14:14:551256 if not virtual_depended_on_files:
1257 return []
1258
1259 if input_api.is_committing:
1260 if input_api.tbr:
1261 return [output_api.PresubmitNotifyResult(
1262 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271263 if input_api.dry_run:
1264 return [output_api.PresubmitNotifyResult(
1265 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551266 if not input_api.change.issue:
1267 return [output_api.PresubmitError(
1268 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:401269 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:551270 output = output_api.PresubmitError
1271 else:
1272 output = output_api.PresubmitNotifyResult
1273
1274 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501275 owner_email, reviewers = (
1276 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1277 input_api,
1278 owners_db.email_regexp,
1279 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551280
1281 owner_email = owner_email or input_api.change.author_email
1282
[email protected]de4f7d22013-05-23 14:27:461283 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511284 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461285 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551286 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1287 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411288
1289 # We strip the /DEPS part that was added by
1290 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1291 # directory.
1292 def StripDeps(path):
1293 start_deps = path.rfind('/DEPS')
1294 if start_deps != -1:
1295 return path[:start_deps]
1296 else:
1297 return path
1298 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551299 for path in missing_files]
1300
1301 if unapproved_dependencies:
1302 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151303 output('You need LGTM from owners of depends-on paths in DEPS that were '
1304 'modified in this CL:\n %s' %
1305 '\n '.join(sorted(unapproved_dependencies)))]
1306 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1307 output_list.append(output(
1308 'Suggested missing target path OWNERS:\n %s' %
1309 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551310 return output_list
1311
1312 return []
1313
1314
[email protected]85218562013-11-22 07:41:401315def _CheckSpamLogging(input_api, output_api):
1316 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1317 black_list = (_EXCLUDED_PATHS +
1318 _TEST_CODE_EXCLUDED_PATHS +
1319 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501320 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191321 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481322 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461323 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121324 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1325 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581326 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591327 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161328 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031329 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151330 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1331 r"^chromecast[\\\/]",
1332 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481333 r"^components[\\\/]browser_watcher[\\\/]"
1334 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311335 r"^components[\\\/]html_viewer[\\\/]"
1336 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461337 # TODO(peter): Remove this exception. https://crbug.com/534537
1338 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1339 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251340 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1341 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241342 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111343 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151344 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111345 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521346 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501347 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361348 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311349 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131350 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001351 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441352 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451353 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021354 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351355 r"dump_file_system.cc$",
1356 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401357 source_file_filter = lambda x: input_api.FilterSourceFile(
1358 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1359
thomasanderson625d3932017-03-29 07:16:581360 log_info = set([])
1361 printf = set([])
[email protected]85218562013-11-22 07:41:401362
1363 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581364 for _, line in f.ChangedContents():
1365 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1366 log_info.add(f.LocalPath())
1367 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1368 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371369
thomasanderson625d3932017-03-29 07:16:581370 if input_api.re.search(r"\bprintf\(", line):
1371 printf.add(f.LocalPath())
1372 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1373 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401374
1375 if log_info:
1376 return [output_api.PresubmitError(
1377 'These files spam the console log with LOG(INFO):',
1378 items=log_info)]
1379 if printf:
1380 return [output_api.PresubmitError(
1381 'These files spam the console log with printf/fprintf:',
1382 items=printf)]
1383 return []
1384
1385
[email protected]49aa76a2013-12-04 06:59:161386def _CheckForAnonymousVariables(input_api, output_api):
1387 """These types are all expected to hold locks while in scope and
1388 so should never be anonymous (which causes them to be immediately
1389 destroyed)."""
1390 they_who_must_be_named = [
1391 'base::AutoLock',
1392 'base::AutoReset',
1393 'base::AutoUnlock',
1394 'SkAutoAlphaRestore',
1395 'SkAutoBitmapShaderInstall',
1396 'SkAutoBlitterChoose',
1397 'SkAutoBounderCommit',
1398 'SkAutoCallProc',
1399 'SkAutoCanvasRestore',
1400 'SkAutoCommentBlock',
1401 'SkAutoDescriptor',
1402 'SkAutoDisableDirectionCheck',
1403 'SkAutoDisableOvalCheck',
1404 'SkAutoFree',
1405 'SkAutoGlyphCache',
1406 'SkAutoHDC',
1407 'SkAutoLockColors',
1408 'SkAutoLockPixels',
1409 'SkAutoMalloc',
1410 'SkAutoMaskFreeImage',
1411 'SkAutoMutexAcquire',
1412 'SkAutoPathBoundsUpdate',
1413 'SkAutoPDFRelease',
1414 'SkAutoRasterClipValidate',
1415 'SkAutoRef',
1416 'SkAutoTime',
1417 'SkAutoTrace',
1418 'SkAutoUnref',
1419 ]
1420 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1421 # bad: base::AutoLock(lock.get());
1422 # not bad: base::AutoLock lock(lock.get());
1423 bad_pattern = input_api.re.compile(anonymous)
1424 # good: new base::AutoLock(lock.get())
1425 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1426 errors = []
1427
1428 for f in input_api.AffectedFiles():
1429 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1430 continue
1431 for linenum, line in f.ChangedContents():
1432 if bad_pattern.search(line) and not good_pattern.search(line):
1433 errors.append('%s:%d' % (f.LocalPath(), linenum))
1434
1435 if errors:
1436 return [output_api.PresubmitError(
1437 'These lines create anonymous variables that need to be named:',
1438 items=errors)]
1439 return []
1440
1441
Peter Kasting4844e46e2018-02-23 07:27:101442def _CheckUniquePtr(input_api, output_api):
1443 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1444 sources = lambda affected_file: input_api.FilterSourceFile(
1445 affected_file,
1446 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1447 input_api.DEFAULT_BLACK_LIST),
1448 white_list=(file_inclusion_pattern,))
1449 return_construct_pattern = input_api.re.compile(
1450 r'(=|\breturn)\s*std::unique_ptr<.*?(?<!])>\([^)]+\)')
1451 null_construct_pattern = input_api.re.compile(
1452 r'\b(?<!<)std::unique_ptr<.*?>\(\)')
1453 errors = []
1454 for f in input_api.AffectedSourceFiles(sources):
1455 for line_number, line in f.ChangedContents():
1456 # Disallow:
1457 # return std::unique_ptr<T>(foo);
1458 # bar = std::unique_ptr<T>(foo);
1459 # But allow:
1460 # return std::unique_ptr<T[]>(foo);
1461 # bar = std::unique_ptr<T[]>(foo);
1462 if return_construct_pattern.search(line):
1463 errors.append(output_api.PresubmitError(
1464 ('%s:%d uses explicit std::unique_ptr constructor. ' +
1465 'Use std::make_unique<T>() instead.') %
1466 (f.LocalPath(), line_number)))
1467 # Disallow:
1468 # std::unique_ptr<T>()
1469 if null_construct_pattern.search(line):
1470 errors.append(output_api.PresubmitError(
1471 '%s:%d uses std::unique_ptr<T>(). Use nullptr instead.' %
1472 (f.LocalPath(), line_number)))
1473 return errors
1474
1475
[email protected]999261d2014-03-03 20:08:081476def _CheckUserActionUpdate(input_api, output_api):
1477 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521478 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081479 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521480 # If actions.xml is already included in the changelist, the PRESUBMIT
1481 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081482 return []
1483
[email protected]999261d2014-03-03 20:08:081484 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1485 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521486 current_actions = None
[email protected]999261d2014-03-03 20:08:081487 for f in input_api.AffectedFiles(file_filter=file_filter):
1488 for line_num, line in f.ChangedContents():
1489 match = input_api.re.search(action_re, line)
1490 if match:
[email protected]2f92dec2014-03-07 19:21:521491 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1492 # loaded only once.
1493 if not current_actions:
1494 with open('tools/metrics/actions/actions.xml') as actions_f:
1495 current_actions = actions_f.read()
1496 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081497 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521498 action = 'name="{0}"'.format(action_name)
1499 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081500 return [output_api.PresubmitPromptWarning(
1501 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521502 'tools/metrics/actions/actions.xml. Please run '
1503 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081504 % (f.LocalPath(), line_num, action_name))]
1505 return []
1506
1507
Daniel Cheng13ca61a882017-08-25 15:11:251508def _ImportJSONCommentEater(input_api):
1509 import sys
1510 sys.path = sys.path + [input_api.os_path.join(
1511 input_api.PresubmitLocalPath(),
1512 'tools', 'json_comment_eater')]
1513 import json_comment_eater
1514 return json_comment_eater
1515
1516
[email protected]99171a92014-06-03 08:44:471517def _GetJSONParseError(input_api, filename, eat_comments=True):
1518 try:
1519 contents = input_api.ReadFile(filename)
1520 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251521 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131522 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471523
1524 input_api.json.loads(contents)
1525 except ValueError as e:
1526 return e
1527 return None
1528
1529
1530def _GetIDLParseError(input_api, filename):
1531 try:
1532 contents = input_api.ReadFile(filename)
1533 idl_schema = input_api.os_path.join(
1534 input_api.PresubmitLocalPath(),
1535 'tools', 'json_schema_compiler', 'idl_schema.py')
1536 process = input_api.subprocess.Popen(
1537 [input_api.python_executable, idl_schema],
1538 stdin=input_api.subprocess.PIPE,
1539 stdout=input_api.subprocess.PIPE,
1540 stderr=input_api.subprocess.PIPE,
1541 universal_newlines=True)
1542 (_, error) = process.communicate(input=contents)
1543 return error or None
1544 except ValueError as e:
1545 return e
1546
1547
1548def _CheckParseErrors(input_api, output_api):
1549 """Check that IDL and JSON files do not contain syntax errors."""
1550 actions = {
1551 '.idl': _GetIDLParseError,
1552 '.json': _GetJSONParseError,
1553 }
[email protected]99171a92014-06-03 08:44:471554 # Most JSON files are preprocessed and support comments, but these do not.
1555 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491556 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471557 ]
1558 # Only run IDL checker on files in these directories.
1559 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491560 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1561 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471562 ]
1563
1564 def get_action(affected_file):
1565 filename = affected_file.LocalPath()
1566 return actions.get(input_api.os_path.splitext(filename)[1])
1567
[email protected]99171a92014-06-03 08:44:471568 def FilterFile(affected_file):
1569 action = get_action(affected_file)
1570 if not action:
1571 return False
1572 path = affected_file.LocalPath()
1573
Sean Kau46e29bc2017-08-28 16:31:161574 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471575 return False
1576
1577 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161578 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471579 return False
1580 return True
1581
1582 results = []
1583 for affected_file in input_api.AffectedFiles(
1584 file_filter=FilterFile, include_deletes=False):
1585 action = get_action(affected_file)
1586 kwargs = {}
1587 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161588 _MatchesFile(input_api, json_no_comments_patterns,
1589 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471590 kwargs['eat_comments'] = False
1591 parse_error = action(input_api,
1592 affected_file.AbsoluteLocalPath(),
1593 **kwargs)
1594 if parse_error:
1595 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1596 (affected_file.LocalPath(), parse_error)))
1597 return results
1598
1599
[email protected]760deea2013-12-10 19:33:491600def _CheckJavaStyle(input_api, output_api):
1601 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471602 import sys
[email protected]760deea2013-12-10 19:33:491603 original_sys_path = sys.path
1604 try:
1605 sys.path = sys.path + [input_api.os_path.join(
1606 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1607 import checkstyle
1608 finally:
1609 # Restore sys.path to what it was before.
1610 sys.path = original_sys_path
1611
1612 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091613 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511614 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491615
1616
Sean Kau46e29bc2017-08-28 16:31:161617def _MatchesFile(input_api, patterns, path):
1618 for pattern in patterns:
1619 if input_api.re.search(pattern, path):
1620 return True
1621 return False
1622
1623
Daniel Cheng7052cdf2017-11-21 19:23:291624def _GetOwnersFilesToCheckForIpcOwners(input_api):
1625 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:171626
Daniel Cheng7052cdf2017-11-21 19:23:291627 Returns:
1628 A dictionary mapping an OWNER file to the list of OWNERS rules it must
1629 contain to cover IPC-related files with noparent reviewer rules.
1630 """
1631 # Whether or not a file affects IPC is (mostly) determined by a simple list
1632 # of filename patterns.
dchenge07de812016-06-20 19:27:171633 file_patterns = [
palmerb19a0932017-01-24 04:00:311634 # Legacy IPC:
dchenge07de812016-06-20 19:27:171635 '*_messages.cc',
1636 '*_messages*.h',
1637 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311638 # Mojo IPC:
dchenge07de812016-06-20 19:27:171639 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:471640 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:171641 '*_struct_traits*.*',
1642 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311643 '*.typemap',
1644 # Android native IPC:
1645 '*.aidl',
1646 # Blink uses a different file naming convention:
1647 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:471648 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:171649 '*StructTraits*.*',
1650 '*TypeConverter*.*',
1651 ]
1652
scottmg7a6ed5ba2016-11-04 18:22:041653 # These third_party directories do not contain IPCs, but contain files
1654 # matching the above patterns, which trigger false positives.
1655 exclude_paths = [
1656 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291657 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041658 ]
1659
dchenge07de812016-06-20 19:27:171660 # Dictionary mapping an OWNERS file path to Patterns.
1661 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1662 # rules ) to a PatternEntry.
1663 # PatternEntry is a dictionary with two keys:
1664 # - 'files': the files that are matched by this pattern
1665 # - 'rules': the per-file rules needed for this pattern
1666 # For example, if we expect OWNERS file to contain rules for *.mojom and
1667 # *_struct_traits*.*, Patterns might look like this:
1668 # {
1669 # '*.mojom': {
1670 # 'files': ...,
1671 # 'rules': [
1672 # 'per-file *.mojom=set noparent',
1673 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1674 # ],
1675 # },
1676 # '*_struct_traits*.*': {
1677 # 'files': ...,
1678 # 'rules': [
1679 # 'per-file *_struct_traits*.*=set noparent',
1680 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1681 # ],
1682 # },
1683 # }
1684 to_check = {}
1685
Daniel Cheng13ca61a882017-08-25 15:11:251686 def AddPatternToCheck(input_file, pattern):
1687 owners_file = input_api.os_path.join(
1688 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1689 if owners_file not in to_check:
1690 to_check[owners_file] = {}
1691 if pattern not in to_check[owners_file]:
1692 to_check[owners_file][pattern] = {
1693 'files': [],
1694 'rules': [
1695 'per-file %s=set noparent' % pattern,
1696 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1697 ]
1698 }
1699 to_check[owners_file][pattern]['files'].append(f)
1700
dchenge07de812016-06-20 19:27:171701 # Iterate through the affected files to see what we actually need to check
1702 # for. We should only nag patch authors about per-file rules if a file in that
1703 # directory would match that pattern. If a directory only contains *.mojom
1704 # files and no *_messages*.h files, we should only nag about rules for
1705 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251706 for f in input_api.AffectedFiles(include_deletes=False):
1707 # Manifest files don't have a strong naming convention. Instead, scan
1708 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161709 if (f.LocalPath().endswith('.json') and
1710 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1711 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251712 json_comment_eater = _ImportJSONCommentEater(input_api)
1713 mostly_json_lines = '\n'.join(f.NewContents())
1714 # Comments aren't allowed in strict JSON, so filter them out.
1715 json_lines = json_comment_eater.Nom(mostly_json_lines)
1716 json_content = input_api.json.loads(json_lines)
1717 if 'interface_provider_specs' in json_content:
1718 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171719 for pattern in file_patterns:
1720 if input_api.fnmatch.fnmatch(
1721 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041722 skip = False
1723 for exclude in exclude_paths:
1724 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1725 skip = True
1726 break
1727 if skip:
1728 continue
Daniel Cheng13ca61a882017-08-25 15:11:251729 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171730 break
1731
Daniel Cheng7052cdf2017-11-21 19:23:291732 return to_check
1733
1734
1735def _CheckIpcOwners(input_api, output_api):
1736 """Checks that affected files involving IPC have an IPC OWNERS rule."""
1737 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
1738
1739 if to_check:
1740 # If there are any OWNERS files to check, there are IPC-related changes in
1741 # this CL. Auto-CC the review list.
1742 output_api.AppendCC('[email protected]')
1743
1744 # Go through the OWNERS files to check, filtering out rules that are already
1745 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:171746 for owners_file, patterns in to_check.iteritems():
1747 try:
1748 with file(owners_file) as f:
1749 lines = set(f.read().splitlines())
1750 for entry in patterns.itervalues():
1751 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1752 ]
1753 except IOError:
1754 # No OWNERS file, so all the rules are definitely missing.
1755 continue
1756
1757 # All the remaining lines weren't found in OWNERS files, so emit an error.
1758 errors = []
1759 for owners_file, patterns in to_check.iteritems():
1760 missing_lines = []
1761 files = []
1762 for pattern, entry in patterns.iteritems():
1763 missing_lines.extend(entry['rules'])
1764 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1765 if missing_lines:
1766 errors.append(
Daniel Cheng52111692017-06-14 08:00:591767 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171768 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1769
1770 results = []
1771 if errors:
vabrf5ce3bf92016-07-11 14:52:411772 if input_api.is_committing:
1773 output = output_api.PresubmitError
1774 else:
1775 output = output_api.PresubmitPromptWarning
1776 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591777 'Found OWNERS files that need to be updated for IPC security ' +
1778 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171779 long_text='\n\n'.join(errors)))
1780
1781 return results
1782
1783
jbriance9e12f162016-11-25 07:57:501784def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311785 """Checks that added or removed lines in non third party affected
1786 header files do not lead to new useless class or struct forward
1787 declaration.
jbriance9e12f162016-11-25 07:57:501788 """
1789 results = []
1790 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1791 input_api.re.MULTILINE)
1792 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1793 input_api.re.MULTILINE)
1794 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311795 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191796 not f.LocalPath().startswith('third_party/blink') and
1797 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311798 not f.LocalPath().startswith('third_party/WebKit') and
1799 not f.LocalPath().startswith('third_party\\WebKit')):
1800 continue
1801
jbriance9e12f162016-11-25 07:57:501802 if not f.LocalPath().endswith('.h'):
1803 continue
1804
1805 contents = input_api.ReadFile(f)
1806 fwd_decls = input_api.re.findall(class_pattern, contents)
1807 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1808
1809 useless_fwd_decls = []
1810 for decl in fwd_decls:
1811 count = sum(1 for _ in input_api.re.finditer(
1812 r'\b%s\b' % input_api.re.escape(decl), contents))
1813 if count == 1:
1814 useless_fwd_decls.append(decl)
1815
1816 if not useless_fwd_decls:
1817 continue
1818
1819 for line in f.GenerateScmDiff().splitlines():
1820 if (line.startswith('-') and not line.startswith('--') or
1821 line.startswith('+') and not line.startswith('++')):
1822 for decl in useless_fwd_decls:
1823 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1824 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241825 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501826 (f.LocalPath(), decl)))
1827 useless_fwd_decls.remove(decl)
1828
1829 return results
1830
1831
dskiba88634f4e2015-08-14 23:03:291832def _CheckAndroidToastUsage(input_api, output_api):
1833 """Checks that code uses org.chromium.ui.widget.Toast instead of
1834 android.widget.Toast (Chromium Toast doesn't force hardware
1835 acceleration on low-end devices, saving memory).
1836 """
1837 toast_import_pattern = input_api.re.compile(
1838 r'^import android\.widget\.Toast;$')
1839
1840 errors = []
1841
1842 sources = lambda affected_file: input_api.FilterSourceFile(
1843 affected_file,
1844 black_list=(_EXCLUDED_PATHS +
1845 _TEST_CODE_EXCLUDED_PATHS +
1846 input_api.DEFAULT_BLACK_LIST +
1847 (r'^chromecast[\\\/].*',
1848 r'^remoting[\\\/].*')),
1849 white_list=(r'.*\.java$',))
1850
1851 for f in input_api.AffectedSourceFiles(sources):
1852 for line_num, line in f.ChangedContents():
1853 if toast_import_pattern.search(line):
1854 errors.append("%s:%d" % (f.LocalPath(), line_num))
1855
1856 results = []
1857
1858 if errors:
1859 results.append(output_api.PresubmitError(
1860 'android.widget.Toast usage is detected. Android toasts use hardware'
1861 ' acceleration, and can be\ncostly on low-end devices. Please use'
1862 ' org.chromium.ui.widget.Toast instead.\n'
1863 'Contact [email protected] if you have any questions.',
1864 errors))
1865
1866 return results
1867
1868
dgnaa68d5e2015-06-10 10:08:221869def _CheckAndroidCrLogUsage(input_api, output_api):
1870 """Checks that new logs using org.chromium.base.Log:
1871 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511872 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221873 """
pkotwicza1dd0b002016-05-16 14:41:041874
torne89540622017-03-24 19:41:301875 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041876 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301877 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041878 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301879 # WebView license viewer code cannot depend on //base; used in stub APK.
1880 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1881 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041882 ]
1883
dgnaa68d5e2015-06-10 10:08:221884 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121885 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1886 class_in_base_pattern = input_api.re.compile(
1887 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1888 has_some_log_import_pattern = input_api.re.compile(
1889 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221890 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121891 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221892 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511893 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221894 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221895
Vincent Scheib16d7b272015-09-15 18:09:071896 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221897 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041898 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1899 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121900
dgnaa68d5e2015-06-10 10:08:221901 tag_decl_errors = []
1902 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121903 tag_errors = []
dgn38736db2015-09-18 19:20:511904 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121905 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221906
1907 for f in input_api.AffectedSourceFiles(sources):
1908 file_content = input_api.ReadFile(f)
1909 has_modified_logs = False
1910
1911 # Per line checks
dgn87d9fb62015-06-12 09:15:121912 if (cr_log_import_pattern.search(file_content) or
1913 (class_in_base_pattern.search(file_content) and
1914 not has_some_log_import_pattern.search(file_content))):
1915 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221916 for line_num, line in f.ChangedContents():
1917
1918 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121919 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221920 if match:
1921 has_modified_logs = True
1922
1923 # Make sure it uses "TAG"
1924 if not match.group('tag') == 'TAG':
1925 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121926 else:
1927 # Report non cr Log function calls in changed lines
1928 for line_num, line in f.ChangedContents():
1929 if log_call_pattern.search(line):
1930 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221931
1932 # Per file checks
1933 if has_modified_logs:
1934 # Make sure the tag is using the "cr" prefix and is not too long
1935 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511936 tag_name = match.group('name') if match else None
1937 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221938 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511939 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221940 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511941 elif '.' in tag_name:
1942 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221943
1944 results = []
1945 if tag_decl_errors:
1946 results.append(output_api.PresubmitPromptWarning(
1947 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511948 '"private static final String TAG = "<package tag>".\n'
1949 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221950 tag_decl_errors))
1951
1952 if tag_length_errors:
1953 results.append(output_api.PresubmitError(
1954 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511955 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221956 tag_length_errors))
1957
1958 if tag_errors:
1959 results.append(output_api.PresubmitPromptWarning(
1960 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1961 tag_errors))
1962
dgn87d9fb62015-06-12 09:15:121963 if util_log_errors:
dgn4401aa52015-04-29 16:26:171964 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121965 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1966 util_log_errors))
1967
dgn38736db2015-09-18 19:20:511968 if tag_with_dot_errors:
1969 results.append(output_api.PresubmitPromptWarning(
1970 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1971 tag_with_dot_errors))
1972
dgn4401aa52015-04-29 16:26:171973 return results
1974
1975
Yoland Yanb92fa522017-08-28 17:37:061976def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1977 """Checks that junit.framework.* is no longer used."""
1978 deprecated_junit_framework_pattern = input_api.re.compile(
1979 r'^import junit\.framework\..*;',
1980 input_api.re.MULTILINE)
1981 sources = lambda x: input_api.FilterSourceFile(
1982 x, white_list=(r'.*\.java$',), black_list=None)
1983 errors = []
1984 for f in input_api.AffectedFiles(sources):
1985 for line_num, line in f.ChangedContents():
1986 if deprecated_junit_framework_pattern.search(line):
1987 errors.append("%s:%d" % (f.LocalPath(), line_num))
1988
1989 results = []
1990 if errors:
1991 results.append(output_api.PresubmitError(
1992 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1993 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1994 ' if you have any question.', errors))
1995 return results
1996
1997
1998def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1999 """Checks that if new Java test classes have inheritance.
2000 Either the new test class is JUnit3 test or it is a JUnit4 test class
2001 with a base class, either case is undesirable.
2002 """
2003 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
2004
2005 sources = lambda x: input_api.FilterSourceFile(
2006 x, white_list=(r'.*Test\.java$',), black_list=None)
2007 errors = []
2008 for f in input_api.AffectedFiles(sources):
2009 if not f.OldContents():
2010 class_declaration_start_flag = False
2011 for line_num, line in f.ChangedContents():
2012 if class_declaration_pattern.search(line):
2013 class_declaration_start_flag = True
2014 if class_declaration_start_flag and ' extends ' in line:
2015 errors.append('%s:%d' % (f.LocalPath(), line_num))
2016 if '{' in line:
2017 class_declaration_start_flag = False
2018
2019 results = []
2020 if errors:
2021 results.append(output_api.PresubmitPromptWarning(
2022 'The newly created files include Test classes that inherits from base'
2023 ' class. Please do not use inheritance in JUnit4 tests or add new'
2024 ' JUnit3 tests. Contact [email protected] if you have any'
2025 ' questions.', errors))
2026 return results
2027
yolandyan45001472016-12-21 21:12:422028def _CheckAndroidTestAnnotationUsage(input_api, output_api):
2029 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
2030 deprecated_annotation_import_pattern = input_api.re.compile(
2031 r'^import android\.test\.suitebuilder\.annotation\..*;',
2032 input_api.re.MULTILINE)
2033 sources = lambda x: input_api.FilterSourceFile(
2034 x, white_list=(r'.*\.java$',), black_list=None)
2035 errors = []
2036 for f in input_api.AffectedFiles(sources):
2037 for line_num, line in f.ChangedContents():
2038 if deprecated_annotation_import_pattern.search(line):
2039 errors.append("%s:%d" % (f.LocalPath(), line_num))
2040
2041 results = []
2042 if errors:
2043 results.append(output_api.PresubmitError(
2044 'Annotations in android.test.suitebuilder.annotation have been'
2045 ' deprecated since API level 24. Please use android.support.test.filters'
2046 ' from //third_party/android_support_test_runner:runner_java instead.'
2047 ' Contact [email protected] if you have any questions.', errors))
2048 return results
2049
2050
agrieve7b6479d82015-10-07 14:24:222051def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
2052 """Checks if MDPI assets are placed in a correct directory."""
2053 file_filter = lambda f: (f.LocalPath().endswith('.png') and
2054 ('/res/drawable/' in f.LocalPath() or
2055 '/res/drawable-ldrtl/' in f.LocalPath()))
2056 errors = []
2057 for f in input_api.AffectedFiles(include_deletes=False,
2058 file_filter=file_filter):
2059 errors.append(' %s' % f.LocalPath())
2060
2061 results = []
2062 if errors:
2063 results.append(output_api.PresubmitError(
2064 'MDPI assets should be placed in /res/drawable-mdpi/ or '
2065 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
2066 '/res/drawable-ldrtl/.\n'
2067 'Contact [email protected] if you have questions.', errors))
2068 return results
2069
2070
Nate Fischer535972b2017-09-16 01:06:182071def _CheckAndroidWebkitImports(input_api, output_api):
2072 """Checks that code uses org.chromium.base.Callback instead of
2073 android.widget.ValueCallback except in the WebView glue layer.
2074 """
2075 valuecallback_import_pattern = input_api.re.compile(
2076 r'^import android\.webkit\.ValueCallback;$')
2077
2078 errors = []
2079
2080 sources = lambda affected_file: input_api.FilterSourceFile(
2081 affected_file,
2082 black_list=(_EXCLUDED_PATHS +
2083 _TEST_CODE_EXCLUDED_PATHS +
2084 input_api.DEFAULT_BLACK_LIST +
2085 (r'^android_webview[\\\/]glue[\\\/].*',)),
2086 white_list=(r'.*\.java$',))
2087
2088 for f in input_api.AffectedSourceFiles(sources):
2089 for line_num, line in f.ChangedContents():
2090 if valuecallback_import_pattern.search(line):
2091 errors.append("%s:%d" % (f.LocalPath(), line_num))
2092
2093 results = []
2094
2095 if errors:
2096 results.append(output_api.PresubmitError(
2097 'android.webkit.ValueCallback usage is detected outside of the glue'
2098 ' layer. To stay compatible with the support library, android.webkit.*'
2099 ' classes should only be used inside the glue layer and'
2100 ' org.chromium.base.Callback should be used instead.',
2101 errors))
2102
2103 return results
2104
2105
agrievef32bcc72016-04-04 14:57:402106class PydepsChecker(object):
2107 def __init__(self, input_api, pydeps_files):
2108 self._file_cache = {}
2109 self._input_api = input_api
2110 self._pydeps_files = pydeps_files
2111
2112 def _LoadFile(self, path):
2113 """Returns the list of paths within a .pydeps file relative to //."""
2114 if path not in self._file_cache:
2115 with open(path) as f:
2116 self._file_cache[path] = f.read()
2117 return self._file_cache[path]
2118
2119 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
2120 """Returns an interable of paths within the .pydep, relativized to //."""
2121 os_path = self._input_api.os_path
2122 pydeps_dir = os_path.dirname(pydeps_path)
2123 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2124 if not l.startswith('*'))
2125 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2126
2127 def _CreateFilesToPydepsMap(self):
2128 """Returns a map of local_path -> list_of_pydeps."""
2129 ret = {}
2130 for pydep_local_path in self._pydeps_files:
2131 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2132 ret.setdefault(path, []).append(pydep_local_path)
2133 return ret
2134
2135 def ComputeAffectedPydeps(self):
2136 """Returns an iterable of .pydeps files that might need regenerating."""
2137 affected_pydeps = set()
2138 file_to_pydeps_map = None
2139 for f in self._input_api.AffectedFiles(include_deletes=True):
2140 local_path = f.LocalPath()
2141 if local_path == 'DEPS':
2142 return self._pydeps_files
2143 elif local_path.endswith('.pydeps'):
2144 if local_path in self._pydeps_files:
2145 affected_pydeps.add(local_path)
2146 elif local_path.endswith('.py'):
2147 if file_to_pydeps_map is None:
2148 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2149 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2150 return affected_pydeps
2151
2152 def DetermineIfStale(self, pydeps_path):
2153 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412154 import difflib
John Budorick47ca3fe2018-02-10 00:53:102155 import os
2156
agrievef32bcc72016-04-04 14:57:402157 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2158 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:102159 env = dict(os.environ)
2160 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:402161 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:102162 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:412163 old_contents = old_pydeps_data[2:]
2164 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402165 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412166 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402167
2168
2169def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2170 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:402171 # This check is for Python dependency lists (.pydeps files), and involves
2172 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
2173 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:282174 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002175 return []
Mostyn Bramley-Moore6b427322017-12-21 22:11:022176 # TODO(agrieve): Update when there's a better way to detect
2177 # this: crbug.com/570091
agrievef32bcc72016-04-04 14:57:402178 is_android = input_api.os_path.exists('third_party/android_tools')
2179 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2180 results = []
2181 # First, check for new / deleted .pydeps.
2182 for f in input_api.AffectedFiles(include_deletes=True):
2183 if f.LocalPath().endswith('.pydeps'):
2184 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2185 results.append(output_api.PresubmitError(
2186 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2187 'remove %s' % f.LocalPath()))
2188 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2189 results.append(output_api.PresubmitError(
2190 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2191 'include %s' % f.LocalPath()))
2192
2193 if results:
2194 return results
2195
2196 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2197
2198 for pydep_path in checker.ComputeAffectedPydeps():
2199 try:
phajdan.jr0d9878552016-11-04 10:49:412200 result = checker.DetermineIfStale(pydep_path)
2201 if result:
2202 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402203 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412204 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2205 'To regenerate, run:\n\n %s' %
2206 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402207 except input_api.subprocess.CalledProcessError as error:
2208 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2209 long_text=error.output)]
2210
2211 return results
2212
2213
glidere61efad2015-02-18 17:39:432214def _CheckSingletonInHeaders(input_api, output_api):
2215 """Checks to make sure no header files have |Singleton<|."""
2216 def FileFilter(affected_file):
2217 # It's ok for base/memory/singleton.h to have |Singleton<|.
2218 black_list = (_EXCLUDED_PATHS +
2219 input_api.DEFAULT_BLACK_LIST +
2220 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2221 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2222
sergeyu34d21222015-09-16 00:11:442223 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432224 files = []
2225 for f in input_api.AffectedSourceFiles(FileFilter):
2226 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2227 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2228 contents = input_api.ReadFile(f)
2229 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242230 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432231 pattern.search(line)):
2232 files.append(f)
2233 break
2234
2235 if files:
yolandyandaabc6d2016-04-18 18:29:392236 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442237 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432238 'Please move them to an appropriate source file so that the ' +
2239 'template gets instantiated in a single compilation unit.',
2240 files) ]
2241 return []
2242
2243
[email protected]fd20b902014-05-09 02:14:532244_DEPRECATED_CSS = [
2245 # Values
2246 ( "-webkit-box", "flex" ),
2247 ( "-webkit-inline-box", "inline-flex" ),
2248 ( "-webkit-flex", "flex" ),
2249 ( "-webkit-inline-flex", "inline-flex" ),
2250 ( "-webkit-min-content", "min-content" ),
2251 ( "-webkit-max-content", "max-content" ),
2252
2253 # Properties
2254 ( "-webkit-background-clip", "background-clip" ),
2255 ( "-webkit-background-origin", "background-origin" ),
2256 ( "-webkit-background-size", "background-size" ),
2257 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442258 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532259
2260 # Functions
2261 ( "-webkit-gradient", "gradient" ),
2262 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2263 ( "-webkit-linear-gradient", "linear-gradient" ),
2264 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2265 ( "-webkit-radial-gradient", "radial-gradient" ),
2266 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2267]
2268
dbeam1ec68ac2016-12-15 05:22:242269def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532270 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252271 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342272 documentation and iOS CSS for dom distiller
2273 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252274 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532275 results = []
dbeam070cfe62014-10-22 06:44:022276 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252277 black_list = (_EXCLUDED_PATHS +
2278 _TEST_CODE_EXCLUDED_PATHS +
2279 input_api.DEFAULT_BLACK_LIST +
2280 (r"^chrome/common/extensions/docs",
2281 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342282 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442283 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252284 r"^native_client_sdk"))
2285 file_filter = lambda f: input_api.FilterSourceFile(
2286 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532287 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2288 for line_num, line in fpath.ChangedContents():
2289 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022290 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532291 results.append(output_api.PresubmitError(
2292 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2293 (fpath.LocalPath(), line_num, deprecated_value, value)))
2294 return results
2295
mohan.reddyf21db962014-10-16 12:26:472296
dbeam070cfe62014-10-22 06:44:022297_DEPRECATED_JS = [
2298 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2299 ( "__defineGetter__", "Object.defineProperty" ),
2300 ( "__defineSetter__", "Object.defineProperty" ),
2301]
2302
dbeam1ec68ac2016-12-15 05:22:242303def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022304 """Make sure that we don't use deprecated JS in Chrome code."""
2305 results = []
2306 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2307 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2308 input_api.DEFAULT_BLACK_LIST)
2309 file_filter = lambda f: input_api.FilterSourceFile(
2310 f, white_list=file_inclusion_pattern, black_list=black_list)
2311 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2312 for lnum, line in fpath.ChangedContents():
2313 for (deprecated, replacement) in _DEPRECATED_JS:
2314 if deprecated in line:
2315 results.append(output_api.PresubmitError(
2316 "%s:%d: Use of deprecated JS %s, use %s instead" %
2317 (fpath.LocalPath(), lnum, deprecated, replacement)))
2318 return results
2319
dpapadd651231d82017-07-21 02:44:472320def _CheckForRiskyJsArrowFunction(line_number, line):
2321 if ' => ' in line:
2322 return "line %d, is using an => (arrow) function\n %s\n" % (
2323 line_number, line)
2324 return ''
2325
2326def _CheckForRiskyJsConstLet(input_api, line_number, line):
2327 if input_api.re.match('^\s*(const|let)\s', line):
2328 return "line %d, is using const/let keyword\n %s\n" % (
2329 line_number, line)
2330 return ''
dbeam070cfe62014-10-22 06:44:022331
dbeam1ec68ac2016-12-15 05:22:242332def _CheckForRiskyJsFeatures(input_api, output_api):
2333 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002334 # 'ui/webui/resources/cr_components are not allowed on ios'
2335 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572336 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002337 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472338 results = []
dbeam1ec68ac2016-12-15 05:22:242339 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472340 arrow_error_lines = []
2341 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242342 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472343 arrow_error_lines += filter(None, [
2344 _CheckForRiskyJsArrowFunction(lnum, line),
2345 ])
dbeam1ec68ac2016-12-15 05:22:242346
dpapadd651231d82017-07-21 02:44:472347 const_let_error_lines += filter(None, [
2348 _CheckForRiskyJsConstLet(input_api, lnum, line),
2349 ])
dbeam1ec68ac2016-12-15 05:22:242350
dpapadd651231d82017-07-21 02:44:472351 if arrow_error_lines:
2352 arrow_error_lines = map(
2353 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2354 results.append(
2355 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2356"""
2357Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242358%s
2359Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2360https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472361""" % f.LocalPath()
2362 ])))
dbeam1ec68ac2016-12-15 05:22:242363
dpapadd651231d82017-07-21 02:44:472364 if const_let_error_lines:
2365 const_let_error_lines = map(
2366 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2367 results.append(
2368 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2369"""
2370Use of const/let keywords detected in:
2371%s
2372Please ensure your code does not run on iOS9 because const/let is not fully
2373supported.
2374https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2375https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2376""" % f.LocalPath()
2377 ])))
2378
2379 return results
dbeam1ec68ac2016-12-15 05:22:242380
rlanday6802cf632017-05-30 17:48:362381def _CheckForRelativeIncludes(input_api, output_api):
2382 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2383 import sys
2384 original_sys_path = sys.path
2385 try:
2386 sys.path = sys.path + [input_api.os_path.join(
2387 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2388 from cpp_checker import CppChecker
2389 finally:
2390 # Restore sys.path to what it was before.
2391 sys.path = original_sys_path
2392
2393 bad_files = {}
2394 for f in input_api.AffectedFiles(include_deletes=False):
2395 if (f.LocalPath().startswith('third_party') and
2396 not f.LocalPath().startswith('third_party/WebKit') and
2397 not f.LocalPath().startswith('third_party\\WebKit')):
2398 continue
2399
2400 if not CppChecker.IsCppFile(f.LocalPath()):
2401 continue
2402
2403 relative_includes = [line for line_num, line in f.ChangedContents()
2404 if "#include" in line and "../" in line]
2405 if not relative_includes:
2406 continue
2407 bad_files[f.LocalPath()] = relative_includes
2408
2409 if not bad_files:
2410 return []
2411
2412 error_descriptions = []
2413 for file_path, bad_lines in bad_files.iteritems():
2414 error_description = file_path
2415 for line in bad_lines:
2416 error_description += '\n ' + line
2417 error_descriptions.append(error_description)
2418
2419 results = []
2420 results.append(output_api.PresubmitError(
2421 'You added one or more relative #include paths (including "../").\n'
2422 'These shouldn\'t be used because they can be used to include headers\n'
2423 'from code that\'s not correctly specified as a dependency in the\n'
2424 'relevant BUILD.gn file(s).',
2425 error_descriptions))
2426
2427 return results
2428
Takeshi Yoshinoe387aa32017-08-02 13:16:132429
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202430def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2431 if not isinstance(key, ast.Str):
2432 return 'Key at line %d must be a string literal' % key.lineno
2433 if not isinstance(value, ast.Dict):
2434 return 'Value at line %d must be a dict' % value.lineno
2435 if len(value.keys) != 1:
2436 return 'Dict at line %d must have single entry' % value.lineno
2437 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2438 return (
2439 'Entry at line %d must have a string literal \'filepath\' as key' %
2440 value.lineno)
2441 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132442
Takeshi Yoshinoe387aa32017-08-02 13:16:132443
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202444def _CheckWatchlistsEntrySyntax(key, value, ast):
2445 if not isinstance(key, ast.Str):
2446 return 'Key at line %d must be a string literal' % key.lineno
2447 if not isinstance(value, ast.List):
2448 return 'Value at line %d must be a list' % value.lineno
2449 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132450
Takeshi Yoshinoe387aa32017-08-02 13:16:132451
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202452def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2453 mismatch_template = (
2454 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2455 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132456
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202457 i = 0
2458 last_key = ''
2459 while True:
2460 if i >= len(wd_dict.keys):
2461 if i >= len(w_dict.keys):
2462 return None
2463 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2464 elif i >= len(w_dict.keys):
2465 return (
2466 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132467
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202468 wd_key = wd_dict.keys[i]
2469 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132470
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202471 result = _CheckWatchlistDefinitionsEntrySyntax(
2472 wd_key, wd_dict.values[i], ast)
2473 if result is not None:
2474 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132475
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202476 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2477 if result is not None:
2478 return 'Bad entry in WATCHLISTS dict: %s' % result
2479
2480 if wd_key.s != w_key.s:
2481 return mismatch_template % (
2482 '%s at line %d' % (wd_key.s, wd_key.lineno),
2483 '%s at line %d' % (w_key.s, w_key.lineno))
2484
2485 if wd_key.s < last_key:
2486 return (
2487 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2488 (wd_key.lineno, w_key.lineno))
2489 last_key = wd_key.s
2490
2491 i = i + 1
2492
2493
2494def _CheckWATCHLISTSSyntax(expression, ast):
2495 if not isinstance(expression, ast.Expression):
2496 return 'WATCHLISTS file must contain a valid expression'
2497 dictionary = expression.body
2498 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2499 return 'WATCHLISTS file must have single dict with exactly two entries'
2500
2501 first_key = dictionary.keys[0]
2502 first_value = dictionary.values[0]
2503 second_key = dictionary.keys[1]
2504 second_value = dictionary.values[1]
2505
2506 if (not isinstance(first_key, ast.Str) or
2507 first_key.s != 'WATCHLIST_DEFINITIONS' or
2508 not isinstance(first_value, ast.Dict)):
2509 return (
2510 'The first entry of the dict in WATCHLISTS file must be '
2511 'WATCHLIST_DEFINITIONS dict')
2512
2513 if (not isinstance(second_key, ast.Str) or
2514 second_key.s != 'WATCHLISTS' or
2515 not isinstance(second_value, ast.Dict)):
2516 return (
2517 'The second entry of the dict in WATCHLISTS file must be '
2518 'WATCHLISTS dict')
2519
2520 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132521
2522
2523def _CheckWATCHLISTS(input_api, output_api):
2524 for f in input_api.AffectedFiles(include_deletes=False):
2525 if f.LocalPath() == 'WATCHLISTS':
2526 contents = input_api.ReadFile(f, 'r')
2527
2528 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202529 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132530 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202531 # Get an AST tree for it and scan the tree for detailed style checking.
2532 expression = input_api.ast.parse(
2533 contents, filename='WATCHLISTS', mode='eval')
2534 except ValueError as e:
2535 return [output_api.PresubmitError(
2536 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2537 except SyntaxError as e:
2538 return [output_api.PresubmitError(
2539 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2540 except TypeError as e:
2541 return [output_api.PresubmitError(
2542 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132543
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202544 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2545 if result is not None:
2546 return [output_api.PresubmitError(result)]
2547 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132548
2549 return []
2550
2551
dgnaa68d5e2015-06-10 10:08:222552def _AndroidSpecificOnUploadChecks(input_api, output_api):
2553 """Groups checks that target android code."""
2554 results = []
dgnaa68d5e2015-06-10 10:08:222555 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222556 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292557 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062558 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2559 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422560 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182561 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222562 return results
2563
2564
[email protected]22c9bd72011-03-27 16:47:392565def _CommonChecks(input_api, output_api):
2566 """Checks common to both upload and commit."""
2567 results = []
2568 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382569 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542570 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:082571
2572 author = input_api.change.author_email
2573 if author and author not in _KNOWN_ROBOTS:
2574 results.extend(
2575 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
2576
[email protected]55459852011-08-10 15:17:192577 results.extend(
[email protected]760deea2013-12-10 19:33:492578 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542579 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182580 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522581 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222582 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442583 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592584 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062585 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122586 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182587 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222588 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302589 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492590 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032591 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492592 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442593 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272594 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072595 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542596 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442597 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392598 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552599 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042600 results.extend(
2601 input_api.canned_checks.CheckChangeHasNoTabs(
2602 input_api,
2603 output_api,
2604 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402605 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162606 results.extend(_CheckForAnonymousVariables(input_api, output_api))
Peter Kasting4844e46e2018-02-23 07:27:102607 results.extend(_CheckUniquePtr(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082608 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242609 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2610 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472611 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042612 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232613 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432614 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402615 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152616 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172617 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502618 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242619 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362620 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132621 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:432622 results.extend(input_api.RunTests(
2623 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
[email protected]2299dcf2012-11-15 19:56:242624
2625 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2626 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2627 input_api, output_api,
2628 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382629 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392630 return results
[email protected]1f7b4172010-01-28 01:17:342631
[email protected]b337cb5b2011-01-23 21:24:052632
[email protected]b8079ae4a2012-12-05 19:56:492633def _CheckPatchFiles(input_api, output_api):
2634 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2635 if f.LocalPath().endswith(('.orig', '.rej'))]
2636 if problems:
2637 return [output_api.PresubmitError(
2638 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032639 else:
2640 return []
[email protected]b8079ae4a2012-12-05 19:56:492641
2642
Kent Tamura5a8755d2017-06-29 23:37:072643def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212644 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2645 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2646 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072647 include_re = input_api.re.compile(
2648 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2649 extension_re = input_api.re.compile(r'\.[a-z]+$')
2650 errors = []
2651 for f in input_api.AffectedFiles():
2652 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2653 continue
2654 found_line_number = None
2655 found_macro = None
2656 for line_num, line in f.ChangedContents():
2657 match = macro_re.search(line)
2658 if match:
2659 found_line_number = line_num
2660 found_macro = match.group(2)
2661 break
2662 if not found_line_number:
2663 continue
2664
2665 found_include = False
2666 for line in f.NewContents():
2667 if include_re.search(line):
2668 found_include = True
2669 break
2670 if found_include:
2671 continue
2672
2673 if not f.LocalPath().endswith('.h'):
2674 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2675 try:
2676 content = input_api.ReadFile(primary_header_path, 'r')
2677 if include_re.search(content):
2678 continue
2679 except IOError:
2680 pass
2681 errors.append('%s:%d %s macro is used without including build/'
2682 'build_config.h.'
2683 % (f.LocalPath(), found_line_number, found_macro))
2684 if errors:
2685 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2686 return []
2687
2688
[email protected]b00342e7f2013-03-26 16:21:542689def _DidYouMeanOSMacro(bad_macro):
2690 try:
2691 return {'A': 'OS_ANDROID',
2692 'B': 'OS_BSD',
2693 'C': 'OS_CHROMEOS',
2694 'F': 'OS_FREEBSD',
2695 'L': 'OS_LINUX',
2696 'M': 'OS_MACOSX',
2697 'N': 'OS_NACL',
2698 'O': 'OS_OPENBSD',
2699 'P': 'OS_POSIX',
2700 'S': 'OS_SOLARIS',
2701 'W': 'OS_WIN'}[bad_macro[3].upper()]
2702 except KeyError:
2703 return ''
2704
2705
2706def _CheckForInvalidOSMacrosInFile(input_api, f):
2707 """Check for sensible looking, totally invalid OS macros."""
2708 preprocessor_statement = input_api.re.compile(r'^\s*#')
2709 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2710 results = []
2711 for lnum, line in f.ChangedContents():
2712 if preprocessor_statement.search(line):
2713 for match in os_macro.finditer(line):
2714 if not match.group(1) in _VALID_OS_MACROS:
2715 good = _DidYouMeanOSMacro(match.group(1))
2716 did_you_mean = ' (did you mean %s?)' % good if good else ''
2717 results.append(' %s:%d %s%s' % (f.LocalPath(),
2718 lnum,
2719 match.group(1),
2720 did_you_mean))
2721 return results
2722
2723
2724def _CheckForInvalidOSMacros(input_api, output_api):
2725 """Check all affected files for invalid OS macros."""
2726 bad_macros = []
2727 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472728 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542729 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2730
2731 if not bad_macros:
2732 return []
2733
2734 return [output_api.PresubmitError(
2735 'Possibly invalid OS macro[s] found. Please fix your code\n'
2736 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2737
lliabraa35bab3932014-10-01 12:16:442738
2739def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2740 """Check all affected files for invalid "if defined" macros."""
2741 ALWAYS_DEFINED_MACROS = (
2742 "TARGET_CPU_PPC",
2743 "TARGET_CPU_PPC64",
2744 "TARGET_CPU_68K",
2745 "TARGET_CPU_X86",
2746 "TARGET_CPU_ARM",
2747 "TARGET_CPU_MIPS",
2748 "TARGET_CPU_SPARC",
2749 "TARGET_CPU_ALPHA",
2750 "TARGET_IPHONE_SIMULATOR",
2751 "TARGET_OS_EMBEDDED",
2752 "TARGET_OS_IPHONE",
2753 "TARGET_OS_MAC",
2754 "TARGET_OS_UNIX",
2755 "TARGET_OS_WIN32",
2756 )
2757 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2758 results = []
2759 for lnum, line in f.ChangedContents():
2760 for match in ifdef_macro.finditer(line):
2761 if match.group(1) in ALWAYS_DEFINED_MACROS:
2762 always_defined = ' %s is always defined. ' % match.group(1)
2763 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2764 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2765 lnum,
2766 always_defined,
2767 did_you_mean))
2768 return results
2769
2770
2771def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2772 """Check all affected files for invalid "if defined" macros."""
2773 bad_macros = []
2774 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212775 if f.LocalPath().startswith('third_party/sqlite/'):
2776 continue
lliabraa35bab3932014-10-01 12:16:442777 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2778 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2779
2780 if not bad_macros:
2781 return []
2782
2783 return [output_api.PresubmitError(
2784 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2785 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2786 bad_macros)]
2787
2788
mlamouria82272622014-09-16 18:45:042789def _CheckForIPCRules(input_api, output_api):
2790 """Check for same IPC rules described in
2791 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2792 """
2793 base_pattern = r'IPC_ENUM_TRAITS\('
2794 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2795 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2796
2797 problems = []
2798 for f in input_api.AffectedSourceFiles(None):
2799 local_path = f.LocalPath()
2800 if not local_path.endswith('.h'):
2801 continue
2802 for line_number, line in f.ChangedContents():
2803 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2804 problems.append(
2805 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2806
2807 if problems:
2808 return [output_api.PresubmitPromptWarning(
2809 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2810 else:
2811 return []
2812
[email protected]b00342e7f2013-03-26 16:21:542813
mostynbb639aca52015-01-07 20:31:232814def _CheckForWindowsLineEndings(input_api, output_api):
2815 """Check source code and known ascii text files for Windows style line
2816 endings.
2817 """
earthdok1b5e0ee2015-03-10 15:19:102818 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232819
2820 file_inclusion_pattern = (
2821 known_text_files,
2822 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2823 )
2824
mostynbb639aca52015-01-07 20:31:232825 problems = []
Andrew Grieve933d12e2017-10-30 20:22:532826 source_file_filter = lambda f: input_api.FilterSourceFile(
2827 f, white_list=file_inclusion_pattern, black_list=None)
2828 for f in input_api.AffectedSourceFiles(source_file_filter):
2829 for line_number, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:232830 if line.endswith('\r\n'):
Andrew Grieve933d12e2017-10-30 20:22:532831 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:232832
2833 if problems:
2834 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2835 'these files to contain Windows style line endings?\n' +
2836 '\n'.join(problems))]
2837
2838 return []
2839
2840
pastarmovj89f7ee12016-09-20 14:58:132841def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2842 lint_filters=None, verbose_level=None):
2843 """Checks that all source files use SYSLOG properly."""
2844 syslog_files = []
2845 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562846 for line_number, line in f.ChangedContents():
2847 if 'SYSLOG' in line:
2848 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2849
pastarmovj89f7ee12016-09-20 14:58:132850 if syslog_files:
2851 return [output_api.PresubmitPromptWarning(
2852 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2853 ' calls.\nFiles to check:\n', items=syslog_files)]
2854 return []
2855
2856
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192857def _CheckCrbugLinksHaveHttps(input_api, output_api):
Miguel Casas68bdb652017-12-19 16:29:092858 """Checks that crbug(.com) links are correctly prefixed by https://,
2859 unless they come in the accepted form TODO(crbug.com/...)
2860 """
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192861 white_list = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2862 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS)
2863 sources = lambda f: input_api.FilterSourceFile(
2864 f, white_list=white_list, black_list=black_list)
2865
2866 pattern = input_api.re.compile(r'//.*(?<!:\/\/)crbug[.com]*')
Miguel Casas68bdb652017-12-19 16:29:092867 accepted_pattern = input_api.re.compile(r'//.*TODO\(crbug[.com]*');
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192868 problems = []
2869 for f in input_api.AffectedSourceFiles(sources):
2870 for line_num, line in f.ChangedContents():
Miguel Casas68bdb652017-12-19 16:29:092871 if pattern.search(line) and not accepted_pattern.search(line):
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192872 problems.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2873
2874 if problems:
2875 return [output_api.PresubmitPromptWarning(
2876 'Found unprefixed crbug.com URL(s), consider prepending https://\n'+
2877 '\n'.join(problems))]
2878 return []
2879
2880
[email protected]1f7b4172010-01-28 01:17:342881def CheckChangeOnUpload(input_api, output_api):
2882 results = []
2883 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472884 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282885 results.extend(
jam93a6ee792017-02-08 23:59:222886 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192887 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222888 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132889 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162890 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Miguel Casas-Sancheze0d46d42017-12-14 15:52:192891 results.extend(_CheckCrbugLinksHaveHttps(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542892 return results
[email protected]ca8d1982009-02-19 16:33:122893
2894
[email protected]1bfb8322014-04-23 01:02:412895def GetTryServerMasterForBot(bot):
2896 """Returns the Try Server master for the given bot.
2897
[email protected]0bb112362014-07-26 04:38:322898 It tries to guess the master from the bot name, but may still fail
2899 and return None. There is no longer a default master.
2900 """
2901 # Potentially ambiguous bot names are listed explicitly.
2902 master_map = {
tandriie5587792016-07-14 00:34:502903 'chromium_presubmit': 'master.tryserver.chromium.linux',
2904 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412905 }
[email protected]0bb112362014-07-26 04:38:322906 master = master_map.get(bot)
2907 if not master:
wnwen4fbaab82016-05-25 12:54:362908 if 'android' in bot:
tandriie5587792016-07-14 00:34:502909 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362910 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502911 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322912 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502913 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322914 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502915 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322916 return master
[email protected]1bfb8322014-04-23 01:02:412917
2918
[email protected]ca8d1982009-02-19 16:33:122919def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542920 results = []
[email protected]1f7b4172010-01-28 01:17:342921 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542922 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272923 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342924 input_api,
2925 output_api,
[email protected]2fdd1f362013-01-16 03:56:032926 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272927
jam93a6ee792017-02-08 23:59:222928 results.extend(
2929 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542930 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2931 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412932 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2933 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542934 return results