blob: efe5574bcdf955101da6ec88c7309313039393a3 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]40d1dbb2012-10-26 07:18:0013 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
14 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2815 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0816 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5417 r"^skia[\\\/].*",
Kent Tamurae9b3a9ec2017-08-31 02:20:1918 r"^third_party[\\\/](WebKit|blink)[\\\/].*",
Mark Mentovaiebb9ddd62017-09-25 17:24:4119 r"^third_party[\\\/]breakpad[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
vapierb2053f542017-03-09 19:46:1026 r"tools[\\\/]md_browser[\\\/].*\.css$",
ehmaldonado78eee2ed2017-03-28 13:16:5427 # Test pages for WebRTC telemetry tests.
28 r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4029)
[email protected]ca8d1982009-02-19 16:33:1230
wnwenbdc444e2016-05-25 13:44:1531
[email protected]06e6d0ff2012-12-11 01:36:4432# Fragment of a regular expression that matches C++ and Objective-C++
33# implementation files.
34_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
35
wnwenbdc444e2016-05-25 13:44:1536
[email protected]06e6d0ff2012-12-11 01:36:4437# Regular expression that matches code only used for test binaries
38# (best effort).
39_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4940 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4441 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
sdefresne1fccb0a2016-12-19 08:10:5342 r'.+_(api|browser|eg|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1243 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4444 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4945 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0546 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4947 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4748 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4949 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0850 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4951 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4452)
[email protected]ca8d1982009-02-19 16:33:1253
wnwenbdc444e2016-05-25 13:44:1554
[email protected]eea609a2011-11-18 13:10:1255_TEST_ONLY_WARNING = (
56 'You might be calling functions intended only for testing from\n'
57 'production code. It is OK to ignore this warning if you know what\n'
58 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5859 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1260
61
[email protected]cf9b78f2012-11-14 11:40:2862_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4063 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2164 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
65 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2866
wnwenbdc444e2016-05-25 13:44:1567
Eric Stevensona9a980972017-09-23 00:04:4168_BANNED_JAVA_FUNCTIONS = (
69 (
70 'StrictMode.allowThreadDiskReads()',
71 (
72 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
73 'directly.',
74 ),
75 False,
76 ),
77 (
78 'StrictMode.allowThreadDiskWrites()',
79 (
80 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
81 'directly.',
82 ),
83 False,
84 ),
85)
86
[email protected]127f18ec2012-06-16 05:05:5987_BANNED_OBJC_FUNCTIONS = (
88 (
89 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2090 (
91 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5992 'prohibited. Please use CrTrackingArea instead.',
93 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
94 ),
95 False,
96 ),
97 (
[email protected]eaae1972014-04-16 04:17:2698 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2099 (
100 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59101 'instead.',
102 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
103 ),
104 False,
105 ),
106 (
107 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20108 (
109 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59110 'Please use |convertPoint:(point) fromView:nil| instead.',
111 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
112 ),
113 True,
114 ),
115 (
116 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20117 (
118 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59119 'Please use |convertPoint:(point) toView:nil| instead.',
120 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
121 ),
122 True,
123 ),
124 (
125 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20126 (
127 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59128 'Please use |convertRect:(point) fromView:nil| instead.',
129 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
130 ),
131 True,
132 ),
133 (
134 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20135 (
136 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59137 'Please use |convertRect:(point) toView:nil| instead.',
138 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
139 ),
140 True,
141 ),
142 (
143 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20144 (
145 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59146 'Please use |convertSize:(point) fromView:nil| instead.',
147 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
148 ),
149 True,
150 ),
151 (
152 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20153 (
154 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59155 'Please use |convertSize:(point) toView:nil| instead.',
156 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
157 ),
158 True,
159 ),
jif65398702016-10-27 10:19:48160 (
161 r"/\s+UTF8String\s*]",
162 (
163 'The use of -[NSString UTF8String] is dangerous as it can return null',
164 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
165 'Please use |SysNSStringToUTF8| instead.',
166 ),
167 True,
168 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34169 (
170 r'__unsafe_unretained',
171 (
172 'The use of __unsafe_unretained is almost certainly wrong, unless',
173 'when interacting with NSFastEnumeration or NSInvocation.',
174 'Please use __weak in files build with ARC, nothing otherwise.',
175 ),
176 False,
177 ),
[email protected]127f18ec2012-06-16 05:05:59178)
179
180
181_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20182 # Make sure that gtest's FRIEND_TEST() macro is not used; the
183 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30184 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20185 (
thomasandersone7caaa9b2017-03-29 19:22:53186 r'\bNULL\b',
187 (
188 'New code should not use NULL. Use nullptr instead.',
189 ),
190 True,
191 (),
192 ),
193 (
[email protected]23e6cbc2012-06-16 18:51:20194 'FRIEND_TEST(',
195 (
[email protected]e3c945502012-06-26 20:01:49196 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20197 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
198 ),
199 False,
[email protected]7345da02012-11-27 14:31:49200 (),
[email protected]23e6cbc2012-06-16 18:51:20201 ),
202 (
thomasanderson4b569052016-09-14 20:15:53203 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
204 (
205 'Chrome clients wishing to select events on X windows should use',
206 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
207 'you are selecting events from the GPU process, or if you are using',
208 'an XDisplay other than gfx::GetXDisplay().',
209 ),
210 True,
211 (
212 r"^ui[\\\/]gl[\\\/].*\.cc$",
213 r"^media[\\\/]gpu[\\\/].*\.cc$",
214 r"^gpu[\\\/].*\.cc$",
215 ),
216 ),
217 (
thomasandersone043e3ce2017-06-08 00:43:20218 r'XInternAtom|xcb_intern_atom',
219 (
thomasanderson11aa41d2017-06-08 22:22:38220 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20221 ),
222 True,
223 (
thomasanderson11aa41d2017-06-08 22:22:38224 r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$",
225 r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20226 r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$",
227 ),
228 ),
229 (
[email protected]23e6cbc2012-06-16 18:51:20230 'ScopedAllowIO',
231 (
satoruxe1396f8a2017-06-01 06:40:39232 'New production code should not use ScopedAllowIO (using it in',
Marijn Kruisselbrink085ef092017-07-12 23:56:55233 'tests is fine). Post a task to a MayBlock task runner instead.',
[email protected]23e6cbc2012-06-16 18:51:20234 ),
[email protected]e3c945502012-06-26 20:01:49235 True,
[email protected]7345da02012-11-27 14:31:49236 (
Marijn Kruisselbrink085ef092017-07-12 23:56:55237 r"^.*(browser|unit)(|_)test[a-z_]*\.cc$",
hajimehoshi2acea432017-03-08 08:55:37238 r"^base[\\\/]memory[\\\/]shared_memory_posix\.cc$",
rayb0088ee52017-04-26 22:35:08239 r"^base[\\\/]process[\\\/]internal_aix\.cc$",
nyad2c548b2015-12-09 03:22:32240 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10241 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
tfarina0923ac52015-01-07 03:21:22242 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
rdevlin.cronin62018a12017-06-22 17:34:06243 r"^chrome[\\\/]browser[\\\/]extensions[\\\/]" +
244 r"chrome_test_extension_loader.cc$",
sky0e07a142016-03-25 21:27:31245 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
philipj3f9d5bde2014-08-28 14:09:09246 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49247 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
248 r"test_info_extractor\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41249 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
250 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25251 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
miu8e0e80c2017-05-31 03:35:57252 r"^media[\\\/]cast[\\\/]test[\\\/]utility[\\\/]" +
253 r"standalone_cast_environment\.cc$",
jamesra03ae492014-10-03 04:26:48254 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
255 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01256 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25257 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
258 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
259 r"embedded_test_server\.cc$",
260 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
Sergey Ulanov937d6eb2017-08-28 22:35:38261 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]" +
262 r"remote_test_server_config\.cc$",
lukasza7947ccd2016-07-28 21:56:25263 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54264 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
sergeyu2c41f9842016-12-10 01:45:16265 r"^remoting[\\\/]protocol[\\\/]webrtc_transport\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53266 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
267 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45268 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
269 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
270 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
271 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
272 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49273 ),
[email protected]23e6cbc2012-06-16 18:51:20274 ),
[email protected]52657f62013-05-20 05:30:31275 (
tomhudsone2c14d552016-05-26 17:07:46276 'setMatrixClip',
277 (
278 'Overriding setMatrixClip() is prohibited; ',
279 'the base function is deprecated. ',
280 ),
281 True,
282 (),
283 ),
284 (
[email protected]52657f62013-05-20 05:30:31285 'SkRefPtr',
286 (
287 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22288 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31289 ),
290 True,
291 (),
292 ),
293 (
294 'SkAutoRef',
295 (
296 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22297 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31298 ),
299 True,
300 (),
301 ),
302 (
303 'SkAutoTUnref',
304 (
305 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22306 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31307 ),
308 True,
309 (),
310 ),
311 (
312 'SkAutoUnref',
313 (
314 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
315 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22316 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31317 ),
318 True,
319 (),
320 ),
[email protected]d89eec82013-12-03 14:10:59321 (
322 r'/HANDLE_EINTR\(.*close',
323 (
324 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
325 'descriptor will be closed, and it is incorrect to retry the close.',
326 'Either call close directly and ignore its return value, or wrap close',
327 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
328 ),
329 True,
330 (),
331 ),
332 (
333 r'/IGNORE_EINTR\((?!.*close)',
334 (
335 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
336 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
337 ),
338 True,
339 (
340 # Files that #define IGNORE_EINTR.
341 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
342 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
343 ),
344 ),
[email protected]ec5b3f02014-04-04 18:43:43345 (
346 r'/v8::Extension\(',
347 (
348 'Do not introduce new v8::Extensions into the code base, use',
349 'gin::Wrappable instead. See http://crbug.com/334679',
350 ),
351 True,
[email protected]f55c90ee62014-04-12 00:50:03352 (
joaodasilva718f87672014-08-30 09:25:49353 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03354 ),
[email protected]ec5b3f02014-04-04 18:43:43355 ),
skyostilf9469f72015-04-20 10:38:52356 (
jame2d1a952016-04-02 00:27:10357 '#pragma comment(lib,',
358 (
359 'Specify libraries to link with in build files and not in the source.',
360 ),
361 True,
362 (),
363 ),
fdorayc4ac18d2017-05-01 21:39:59364 (
Gabriel Charette6127a86f2017-09-22 14:33:59365 'BrowserThread::FILE',
Gabriel Charette664e4482017-06-13 19:55:29366 (
367 'The non-UI/IO BrowserThreads are deprecated, please migrate this',
368 'code to TaskScheduler. See https://goo.gl/mDSxKl for details.',
369 'For questions, contact base/task_scheduler/OWNERS.',
370 ),
371 True,
372 (),
373 ),
374 (
gabd52c912a2017-05-11 04:15:59375 'base::SequenceChecker',
376 (
377 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
378 ),
379 False,
380 (),
381 ),
382 (
383 'base::ThreadChecker',
384 (
385 'Consider using THREAD_CHECKER macros instead of the class directly.',
386 ),
387 False,
388 (),
389 ),
dbeamb6f4fde2017-06-15 04:03:06390 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06391 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
392 (
393 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
394 'deprecated (http://crbug.com/634507). Please avoid converting away',
395 'from the Time types in Chromium code, especially if any math is',
396 'being done on time values. For interfacing with platform/library',
397 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
398 'type converter methods instead. For faking TimeXXX values (for unit',
399 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
400 'other use cases, please contact base/time/OWNERS.',
401 ),
402 False,
403 (),
404 ),
405 (
dbeamb6f4fde2017-06-15 04:03:06406 'CallJavascriptFunctionUnsafe',
407 (
408 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
409 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
410 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
411 ),
412 False,
413 (
414 r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$',
415 r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$',
416 r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$',
417 ),
418 ),
dskiba1474c2bfd62017-07-20 02:19:24419 (
420 'leveldb::DB::Open',
421 (
422 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
423 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
424 "Chrome's tracing, making their memory usage visible.",
425 ),
426 True,
427 (
428 r'^third_party/leveldatabase/.*\.(cc|h)$',
429 ),
Gabriel Charette0592c3a2017-07-26 12:02:04430 ),
431 (
Gabriel Charetted9839bc2017-07-29 14:17:47432 'MessageLoop::QuitWhenIdleClosure',
Gabriel Charette0592c3a2017-07-26 12:02:04433 (
Robert Liao64b7ab22017-08-04 23:03:43434 'MessageLoop::QuitWhenIdleClosure is deprecated. Please migrate to',
435 'Runloop.',
Gabriel Charette0592c3a2017-07-26 12:02:04436 ),
437 True,
438 (),
Gabriel Charetted9839bc2017-07-29 14:17:47439 ),
440 (
441 'RunLoop::QuitCurrent',
442 (
Robert Liao64b7ab22017-08-04 23:03:43443 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
444 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47445 ),
446 True,
447 (),
Gabriel Charettea44975052017-08-21 23:14:04448 ),
449 (
450 'base::ScopedMockTimeMessageLoopTaskRunner',
451 (
452 'ScopedMockTimeMessageLoopTaskRunner is deprecated.',
453 ),
454 True,
455 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57456 ),
457 (
458 r'std::regex',
459 (
460 'Using std::regex adds unnecessary binary size to Chrome. Please use',
461 're2::RE2 instead (crbug/755321)',
462 ),
463 True,
464 (),
dskiba1474c2bfd62017-07-20 02:19:24465 )
[email protected]127f18ec2012-06-16 05:05:59466)
467
wnwenbdc444e2016-05-25 13:44:15468
mlamouria82272622014-09-16 18:45:04469_IPC_ENUM_TRAITS_DEPRECATED = (
470 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
471 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
472
[email protected]127f18ec2012-06-16 05:05:59473
Sean Kau46e29bc2017-08-28 16:31:16474# These paths contain test data and other known invalid JSON files.
475_KNOWN_INVALID_JSON_FILE_PATTERNS = [
476 r'test[\\\/]data[\\\/]',
477 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
478 r'^third_party[\\\/]protobuf[\\\/]',
479]
480
481
[email protected]b00342e7f2013-03-26 16:21:54482_VALID_OS_MACROS = (
483 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08484 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54485 'OS_ANDROID',
486 'OS_BSD',
487 'OS_CAT', # For testing.
488 'OS_CHROMEOS',
489 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37490 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54491 'OS_IOS',
492 'OS_LINUX',
493 'OS_MACOSX',
494 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21495 'OS_NACL_NONSFI',
496 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12497 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54498 'OS_OPENBSD',
499 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37500 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54501 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54502 'OS_WIN',
503)
504
505
agrievef32bcc72016-04-04 14:57:40506_ANDROID_SPECIFIC_PYDEPS_FILES = [
507 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04508 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58509 'build/secondary/third_party/android_platform/'
510 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19511 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40512]
513
wnwenbdc444e2016-05-25 13:44:15514
agrievef32bcc72016-04-04 14:57:40515_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40516]
517
wnwenbdc444e2016-05-25 13:44:15518
agrievef32bcc72016-04-04 14:57:40519_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
520
521
[email protected]55459852011-08-10 15:17:19522def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
523 """Attempts to prevent use of functions intended only for testing in
524 non-testing code. For now this is just a best-effort implementation
525 that ignores header files and may have some false positives. A
526 better implementation would probably need a proper C++ parser.
527 """
528 # We only scan .cc files and the like, as the declaration of
529 # for-testing functions in header files are hard to distinguish from
530 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44531 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19532
jochenc0d4808c2015-07-27 09:25:42533 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19534 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09535 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19536 exclusion_pattern = input_api.re.compile(
537 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
538 base_function_pattern, base_function_pattern))
539
540 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44541 black_list = (_EXCLUDED_PATHS +
542 _TEST_CODE_EXCLUDED_PATHS +
543 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19544 return input_api.FilterSourceFile(
545 affected_file,
546 white_list=(file_inclusion_pattern, ),
547 black_list=black_list)
548
549 problems = []
550 for f in input_api.AffectedSourceFiles(FilterFile):
551 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24552 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03553 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46554 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03555 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19556 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03557 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19558
559 if problems:
[email protected]f7051d52013-04-02 18:31:42560 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03561 else:
562 return []
[email protected]55459852011-08-10 15:17:19563
564
[email protected]10689ca2011-09-02 02:31:54565def _CheckNoIOStreamInHeaders(input_api, output_api):
566 """Checks to make sure no .h files include <iostream>."""
567 files = []
568 pattern = input_api.re.compile(r'^#include\s*<iostream>',
569 input_api.re.MULTILINE)
570 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
571 if not f.LocalPath().endswith('.h'):
572 continue
573 contents = input_api.ReadFile(f)
574 if pattern.search(contents):
575 files.append(f)
576
577 if len(files):
yolandyandaabc6d2016-04-18 18:29:39578 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06579 'Do not #include <iostream> in header files, since it inserts static '
580 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54581 '#include <ostream>. See http://crbug.com/94794',
582 files) ]
583 return []
584
585
[email protected]72df4e782012-06-21 16:28:18586def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52587 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18588 problems = []
589 for f in input_api.AffectedFiles():
590 if (not f.LocalPath().endswith(('.cc', '.mm'))):
591 continue
592
593 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04594 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18595 problems.append(' %s:%d' % (f.LocalPath(), line_num))
596
597 if not problems:
598 return []
599 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
600 '\n'.join(problems))]
601
602
danakj61c1aa22015-10-26 19:55:52603def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57604 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52605 errors = []
606 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
607 input_api.re.MULTILINE)
608 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
609 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
610 continue
611 for lnum, line in f.ChangedContents():
612 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17613 errors.append(output_api.PresubmitError(
614 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57615 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17616 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52617 return errors
618
619
mcasasb7440c282015-02-04 14:52:19620def _FindHistogramNameInLine(histogram_name, line):
621 """Tries to find a histogram name or prefix in a line."""
622 if not "affected-histogram" in line:
623 return histogram_name in line
624 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
625 # the histogram_name.
626 if not '"' in line:
627 return False
628 histogram_prefix = line.split('\"')[1]
629 return histogram_prefix in histogram_name
630
631
632def _CheckUmaHistogramChanges(input_api, output_api):
633 """Check that UMA histogram names in touched lines can still be found in other
634 lines of the patch or in histograms.xml. Note that this check would not catch
635 the reverse: changes in histograms.xml not matched in the code itself."""
636 touched_histograms = []
637 histograms_xml_modifications = []
638 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
639 for f in input_api.AffectedFiles():
640 # If histograms.xml itself is modified, keep the modified lines for later.
641 if f.LocalPath().endswith(('histograms.xml')):
642 histograms_xml_modifications = f.ChangedContents()
643 continue
644 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
645 continue
646 for line_num, line in f.ChangedContents():
647 found = pattern.search(line)
648 if found:
649 touched_histograms.append([found.group(1), f, line_num])
650
651 # Search for the touched histogram names in the local modifications to
652 # histograms.xml, and, if not found, on the base histograms.xml file.
653 unmatched_histograms = []
654 for histogram_info in touched_histograms:
655 histogram_name_found = False
656 for line_num, line in histograms_xml_modifications:
657 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
658 if histogram_name_found:
659 break
660 if not histogram_name_found:
661 unmatched_histograms.append(histogram_info)
662
eromanb90c82e7e32015-04-01 15:13:49663 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19664 problems = []
665 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49666 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19667 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45668 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19669 histogram_name_found = False
670 for line in histograms_xml:
671 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
672 if histogram_name_found:
673 break
674 if not histogram_name_found:
675 problems.append(' [%s:%d] %s' %
676 (f.LocalPath(), line_num, histogram_name))
677
678 if not problems:
679 return []
680 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
681 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49682 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19683
wnwenbdc444e2016-05-25 13:44:15684
yolandyandaabc6d2016-04-18 18:29:39685def _CheckFlakyTestUsage(input_api, output_api):
686 """Check that FlakyTest annotation is our own instead of the android one"""
687 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
688 files = []
689 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
690 if f.LocalPath().endswith('Test.java'):
691 if pattern.search(input_api.ReadFile(f)):
692 files.append(f)
693 if len(files):
694 return [output_api.PresubmitError(
695 'Use org.chromium.base.test.util.FlakyTest instead of '
696 'android.test.FlakyTest',
697 files)]
698 return []
mcasasb7440c282015-02-04 14:52:19699
wnwenbdc444e2016-05-25 13:44:15700
[email protected]8ea5d4b2011-09-13 21:49:22701def _CheckNoNewWStrings(input_api, output_api):
702 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27703 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22704 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20705 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57706 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34707 '/win/' in f.LocalPath() or
708 'chrome_elf' in f.LocalPath() or
709 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20710 continue
[email protected]8ea5d4b2011-09-13 21:49:22711
[email protected]a11dbe9b2012-08-07 01:32:58712 allowWString = False
[email protected]b5c24292011-11-28 14:38:20713 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58714 if 'presubmit: allow wstring' in line:
715 allowWString = True
716 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27717 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58718 allowWString = False
719 else:
720 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22721
[email protected]55463aa62011-10-12 00:48:27722 if not problems:
723 return []
724 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58725 ' If you are calling a cross-platform API that accepts a wstring, '
726 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27727 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22728
729
[email protected]2a8ac9c2011-10-19 17:20:44730def _CheckNoDEPSGIT(input_api, output_api):
731 """Make sure .DEPS.git is never modified manually."""
732 if any(f.LocalPath().endswith('.DEPS.git') for f in
733 input_api.AffectedFiles()):
734 return [output_api.PresubmitError(
735 'Never commit changes to .DEPS.git. This file is maintained by an\n'
736 'automated system based on what\'s in DEPS and your changes will be\n'
737 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34738 '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:44739 'for more information')]
740 return []
741
742
tandriief664692014-09-23 14:51:47743def _CheckValidHostsInDEPS(input_api, output_api):
744 """Checks that DEPS file deps are from allowed_hosts."""
745 # Run only if DEPS file has been modified to annoy fewer bystanders.
746 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
747 return []
748 # Outsource work to gclient verify
749 try:
750 input_api.subprocess.check_output(['gclient', 'verify'])
751 return []
752 except input_api.subprocess.CalledProcessError, error:
753 return [output_api.PresubmitError(
754 'DEPS file must have only git dependencies.',
755 long_text=error.output)]
756
757
[email protected]127f18ec2012-06-16 05:05:59758def _CheckNoBannedFunctions(input_api, output_api):
759 """Make sure that banned functions are not used."""
760 warnings = []
761 errors = []
762
wnwenbdc444e2016-05-25 13:44:15763 def IsBlacklisted(affected_file, blacklist):
764 local_path = affected_file.LocalPath()
765 for item in blacklist:
766 if input_api.re.match(item, local_path):
767 return True
768 return False
769
770 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
771 matched = False
772 if func_name[0:1] == '/':
773 regex = func_name[1:]
774 if input_api.re.search(regex, line):
775 matched = True
776 elif func_name in line:
dchenge07de812016-06-20 19:27:17777 matched = True
wnwenbdc444e2016-05-25 13:44:15778 if matched:
dchenge07de812016-06-20 19:27:17779 problems = warnings
wnwenbdc444e2016-05-25 13:44:15780 if error:
dchenge07de812016-06-20 19:27:17781 problems = errors
wnwenbdc444e2016-05-25 13:44:15782 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
783 for message_line in message:
784 problems.append(' %s' % message_line)
785
Eric Stevensona9a980972017-09-23 00:04:41786 file_filter = lambda f: f.LocalPath().endswith(('.java'))
787 for f in input_api.AffectedFiles(file_filter=file_filter):
788 for line_num, line in f.ChangedContents():
789 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
790 CheckForMatch(f, line_num, line, func_name, message, error)
791
[email protected]127f18ec2012-06-16 05:05:59792 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
793 for f in input_api.AffectedFiles(file_filter=file_filter):
794 for line_num, line in f.ChangedContents():
795 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15796 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59797
798 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
799 for f in input_api.AffectedFiles(file_filter=file_filter):
800 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49801 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49802 if IsBlacklisted(f, excluded_paths):
803 continue
wnwenbdc444e2016-05-25 13:44:15804 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59805
806 result = []
807 if (warnings):
808 result.append(output_api.PresubmitPromptWarning(
809 'Banned functions were used.\n' + '\n'.join(warnings)))
810 if (errors):
811 result.append(output_api.PresubmitError(
812 'Banned functions were used.\n' + '\n'.join(errors)))
813 return result
814
815
[email protected]6c063c62012-07-11 19:11:06816def _CheckNoPragmaOnce(input_api, output_api):
817 """Make sure that banned functions are not used."""
818 files = []
819 pattern = input_api.re.compile(r'^#pragma\s+once',
820 input_api.re.MULTILINE)
821 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
822 if not f.LocalPath().endswith('.h'):
823 continue
824 contents = input_api.ReadFile(f)
825 if pattern.search(contents):
826 files.append(f)
827
828 if files:
829 return [output_api.PresubmitError(
830 'Do not use #pragma once in header files.\n'
831 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
832 files)]
833 return []
834
[email protected]127f18ec2012-06-16 05:05:59835
[email protected]e7479052012-09-19 00:26:12836def _CheckNoTrinaryTrueFalse(input_api, output_api):
837 """Checks to make sure we don't introduce use of foo ? true : false."""
838 problems = []
839 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
840 for f in input_api.AffectedFiles():
841 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
842 continue
843
844 for line_num, line in f.ChangedContents():
845 if pattern.match(line):
846 problems.append(' %s:%d' % (f.LocalPath(), line_num))
847
848 if not problems:
849 return []
850 return [output_api.PresubmitPromptWarning(
851 'Please consider avoiding the "? true : false" pattern if possible.\n' +
852 '\n'.join(problems))]
853
854
[email protected]55f9f382012-07-31 11:02:18855def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28856 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18857 change. Breaking - rules is an error, breaking ! rules is a
858 warning.
859 """
mohan.reddyf21db962014-10-16 12:26:47860 import sys
[email protected]55f9f382012-07-31 11:02:18861 # We need to wait until we have an input_api object and use this
862 # roundabout construct to import checkdeps because this file is
863 # eval-ed and thus doesn't have __file__.
864 original_sys_path = sys.path
865 try:
866 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47867 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18868 import checkdeps
869 from cpp_checker import CppChecker
rhalavati08acd232017-04-03 07:23:28870 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18871 from rules import Rule
872 finally:
873 # Restore sys.path to what it was before.
874 sys.path = original_sys_path
875
876 added_includes = []
rhalavati08acd232017-04-03 07:23:28877 added_imports = []
[email protected]55f9f382012-07-31 11:02:18878 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28879 if CppChecker.IsCppFile(f.LocalPath()):
880 changed_lines = [line for line_num, line in f.ChangedContents()]
881 added_includes.append([f.LocalPath(), changed_lines])
882 elif ProtoChecker.IsProtoFile(f.LocalPath()):
883 changed_lines = [line for line_num, line in f.ChangedContents()]
884 added_imports.append([f.LocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18885
[email protected]26385172013-05-09 23:11:35886 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18887
888 error_descriptions = []
889 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28890 error_subjects = set()
891 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18892 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
893 added_includes):
894 description_with_path = '%s\n %s' % (path, rule_description)
895 if rule_type == Rule.DISALLOW:
896 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28897 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18898 else:
899 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28900 warning_subjects.add("#includes")
901
902 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
903 added_imports):
904 description_with_path = '%s\n %s' % (path, rule_description)
905 if rule_type == Rule.DISALLOW:
906 error_descriptions.append(description_with_path)
907 error_subjects.add("imports")
908 else:
909 warning_descriptions.append(description_with_path)
910 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18911
912 results = []
913 if error_descriptions:
914 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28915 'You added one or more %s that violate checkdeps rules.'
916 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18917 error_descriptions))
918 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42919 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28920 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18921 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28922 '%s? See relevant DEPS file(s) for details and contacts.' %
923 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18924 warning_descriptions))
925 return results
926
927
[email protected]fbcafe5a2012-08-08 15:31:22928def _CheckFilePermissions(input_api, output_api):
929 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15930 if input_api.platform == 'win32':
931 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29932 checkperms_tool = input_api.os_path.join(
933 input_api.PresubmitLocalPath(),
934 'tools', 'checkperms', 'checkperms.py')
935 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47936 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22937 for f in input_api.AffectedFiles():
938 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11939 try:
940 input_api.subprocess.check_output(args)
941 return []
942 except input_api.subprocess.CalledProcessError as error:
943 return [output_api.PresubmitError(
944 'checkperms.py failed:',
945 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22946
947
robertocn832f5992017-01-04 19:01:30948def _CheckTeamTags(input_api, output_api):
949 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
950 checkteamtags_tool = input_api.os_path.join(
951 input_api.PresubmitLocalPath(),
952 'tools', 'checkteamtags', 'checkteamtags.py')
953 args = [input_api.python_executable, checkteamtags_tool,
954 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22955 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30956 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
957 'OWNERS']
958 try:
959 if files:
960 input_api.subprocess.check_output(args + files)
961 return []
962 except input_api.subprocess.CalledProcessError as error:
963 return [output_api.PresubmitError(
964 'checkteamtags.py failed:',
965 long_text=error.output)]
966
967
[email protected]c8278b32012-10-30 20:35:49968def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
969 """Makes sure we don't include ui/aura/window_property.h
970 in header files.
971 """
972 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
973 errors = []
974 for f in input_api.AffectedFiles():
975 if not f.LocalPath().endswith('.h'):
976 continue
977 for line_num, line in f.ChangedContents():
978 if pattern.match(line):
979 errors.append(' %s:%d' % (f.LocalPath(), line_num))
980
981 results = []
982 if errors:
983 results.append(output_api.PresubmitError(
984 'Header files should not include ui/aura/window_property.h', errors))
985 return results
986
987
[email protected]70ca77752012-11-20 03:45:03988def _CheckForVersionControlConflictsInFile(input_api, f):
989 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
990 errors = []
991 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23992 if f.LocalPath().endswith('.md'):
993 # First-level headers in markdown look a lot like version control
994 # conflict markers. http://daringfireball.net/projects/markdown/basics
995 continue
[email protected]70ca77752012-11-20 03:45:03996 if pattern.match(line):
997 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
998 return errors
999
1000
1001def _CheckForVersionControlConflicts(input_api, output_api):
1002 """Usually this is not intentional and will cause a compile failure."""
1003 errors = []
1004 for f in input_api.AffectedFiles():
1005 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1006
1007 results = []
1008 if errors:
1009 results.append(output_api.PresubmitError(
1010 'Version control conflict markers found, please resolve.', errors))
1011 return results
1012
estadee17314a02017-01-12 16:22:161013def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1014 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1015 errors = []
1016 for f in input_api.AffectedFiles():
1017 for line_num, line in f.ChangedContents():
1018 if pattern.search(line):
1019 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1020
1021 results = []
1022 if errors:
1023 results.append(output_api.PresubmitPromptWarning(
1024 'Found Google support URL addressed by answer number. Please replace with '
1025 'a p= identifier instead. See crbug.com/679462\n', errors))
1026 return results
1027
[email protected]70ca77752012-11-20 03:45:031028
[email protected]06e6d0ff2012-12-11 01:36:441029def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1030 def FilterFile(affected_file):
1031 """Filter function for use with input_api.AffectedSourceFiles,
1032 below. This filters out everything except non-test files from
1033 top-level directories that generally speaking should not hard-code
1034 service URLs (e.g. src/android_webview/, src/content/ and others).
1035 """
1036 return input_api.FilterSourceFile(
1037 affected_file,
[email protected]78bb39d62012-12-11 15:11:561038 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441039 black_list=(_EXCLUDED_PATHS +
1040 _TEST_CODE_EXCLUDED_PATHS +
1041 input_api.DEFAULT_BLACK_LIST))
1042
reillyi38965732015-11-16 18:27:331043 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1044 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461045 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1046 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441047 problems = [] # items are (filename, line_number, line)
1048 for f in input_api.AffectedSourceFiles(FilterFile):
1049 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461050 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441051 problems.append((f.LocalPath(), line_num, line))
1052
1053 if problems:
[email protected]f7051d52013-04-02 18:31:421054 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441055 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581056 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441057 [' %s:%d: %s' % (
1058 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031059 else:
1060 return []
[email protected]06e6d0ff2012-12-11 01:36:441061
1062
[email protected]d2530012013-01-25 16:39:271063def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1064 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311065 The native_client_sdk directory is excluded because it has auto-generated PNG
1066 files for documentation.
[email protected]d2530012013-01-25 16:39:271067 """
[email protected]d2530012013-01-25 16:39:271068 errors = []
binji0dcdf342014-12-12 18:32:311069 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1070 black_list = (r'^native_client_sdk[\\\/]',)
1071 file_filter = lambda f: input_api.FilterSourceFile(
1072 f, white_list=white_list, black_list=black_list)
1073 for f in input_api.AffectedFiles(include_deletes=False,
1074 file_filter=file_filter):
1075 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271076
1077 results = []
1078 if errors:
1079 results.append(output_api.PresubmitError(
1080 'The name of PNG files should not have abbreviations. \n'
1081 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1082 'Contact [email protected] if you have questions.', errors))
1083 return results
1084
1085
Daniel Cheng4dcdb6b2017-04-13 08:30:171086def _ExtractAddRulesFromParsedDeps(parsed_deps):
1087 """Extract the rules that add dependencies from a parsed DEPS file.
1088
1089 Args:
1090 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1091 add_rules = set()
1092 add_rules.update([
1093 rule[1:] for rule in parsed_deps.get('include_rules', [])
1094 if rule.startswith('+') or rule.startswith('!')
1095 ])
1096 for specific_file, rules in parsed_deps.get('specific_include_rules',
1097 {}).iteritems():
1098 add_rules.update([
1099 rule[1:] for rule in rules
1100 if rule.startswith('+') or rule.startswith('!')
1101 ])
1102 return add_rules
1103
1104
1105def _ParseDeps(contents):
1106 """Simple helper for parsing DEPS files."""
1107 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171108 class _VarImpl:
1109
1110 def __init__(self, local_scope):
1111 self._local_scope = local_scope
1112
1113 def Lookup(self, var_name):
1114 """Implements the Var syntax."""
1115 try:
1116 return self._local_scope['vars'][var_name]
1117 except KeyError:
1118 raise Exception('Var is not defined: %s' % var_name)
1119
1120 local_scope = {}
1121 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171122 'Var': _VarImpl(local_scope).Lookup,
1123 }
1124 exec contents in global_scope, local_scope
1125 return local_scope
1126
1127
1128def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081129 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411130 a set of DEPS entries that we should look up.
1131
1132 For a directory (rather than a specific filename) we fake a path to
1133 a specific filename by adding /DEPS. This is chosen as a file that
1134 will seldom or never be subject to per-file include_rules.
1135 """
[email protected]2b438d62013-11-14 17:54:141136 # We ignore deps entries on auto-generated directories.
1137 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081138
Daniel Cheng4dcdb6b2017-04-13 08:30:171139 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1140 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1141
1142 added_deps = new_deps.difference(old_deps)
1143
[email protected]2b438d62013-11-14 17:54:141144 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171145 for added_dep in added_deps:
1146 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1147 continue
1148 # Assume that a rule that ends in .h is a rule for a specific file.
1149 if added_dep.endswith('.h'):
1150 results.add(added_dep)
1151 else:
1152 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081153 return results
1154
1155
[email protected]e871964c2013-05-13 14:14:551156def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1157 """When a dependency prefixed with + is added to a DEPS file, we
1158 want to make sure that the change is reviewed by an OWNER of the
1159 target file or directory, to avoid layering violations from being
1160 introduced. This check verifies that this happens.
1161 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171162 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241163
1164 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191165 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241166 for f in input_api.AffectedFiles(include_deletes=False,
1167 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551168 filename = input_api.os_path.basename(f.LocalPath())
1169 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171170 virtual_depended_on_files.update(_CalculateAddedDeps(
1171 input_api.os_path,
1172 '\n'.join(f.OldContents()),
1173 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551174
[email protected]e871964c2013-05-13 14:14:551175 if not virtual_depended_on_files:
1176 return []
1177
1178 if input_api.is_committing:
1179 if input_api.tbr:
1180 return [output_api.PresubmitNotifyResult(
1181 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271182 if input_api.dry_run:
1183 return [output_api.PresubmitNotifyResult(
1184 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551185 if not input_api.change.issue:
1186 return [output_api.PresubmitError(
1187 "DEPS approval by OWNERS check failed: this change has "
1188 "no Rietveld issue number, so we can't check it for approvals.")]
1189 output = output_api.PresubmitError
1190 else:
1191 output = output_api.PresubmitNotifyResult
1192
1193 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501194 owner_email, reviewers = (
1195 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1196 input_api,
1197 owners_db.email_regexp,
1198 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551199
1200 owner_email = owner_email or input_api.change.author_email
1201
[email protected]de4f7d22013-05-23 14:27:461202 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511203 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461204 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551205 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1206 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411207
1208 # We strip the /DEPS part that was added by
1209 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1210 # directory.
1211 def StripDeps(path):
1212 start_deps = path.rfind('/DEPS')
1213 if start_deps != -1:
1214 return path[:start_deps]
1215 else:
1216 return path
1217 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551218 for path in missing_files]
1219
1220 if unapproved_dependencies:
1221 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151222 output('You need LGTM from owners of depends-on paths in DEPS that were '
1223 'modified in this CL:\n %s' %
1224 '\n '.join(sorted(unapproved_dependencies)))]
1225 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1226 output_list.append(output(
1227 'Suggested missing target path OWNERS:\n %s' %
1228 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551229 return output_list
1230
1231 return []
1232
1233
[email protected]85218562013-11-22 07:41:401234def _CheckSpamLogging(input_api, output_api):
1235 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1236 black_list = (_EXCLUDED_PATHS +
1237 _TEST_CODE_EXCLUDED_PATHS +
1238 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501239 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191240 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481241 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461242 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121243 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1244 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581245 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591246 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161247 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031248 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151249 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1250 r"^chromecast[\\\/]",
1251 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481252 r"^components[\\\/]browser_watcher[\\\/]"
1253 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311254 r"^components[\\\/]html_viewer[\\\/]"
1255 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461256 # TODO(peter): Remove this exception. https://crbug.com/534537
1257 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1258 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251259 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1260 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241261 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111262 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151263 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111264 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521265 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501266 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361267 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311268 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131269 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001270 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441271 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451272 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021273 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351274 r"dump_file_system.cc$",
1275 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401276 source_file_filter = lambda x: input_api.FilterSourceFile(
1277 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1278
thomasanderson625d3932017-03-29 07:16:581279 log_info = set([])
1280 printf = set([])
[email protected]85218562013-11-22 07:41:401281
1282 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581283 for _, line in f.ChangedContents():
1284 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1285 log_info.add(f.LocalPath())
1286 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1287 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371288
thomasanderson625d3932017-03-29 07:16:581289 if input_api.re.search(r"\bprintf\(", line):
1290 printf.add(f.LocalPath())
1291 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1292 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401293
1294 if log_info:
1295 return [output_api.PresubmitError(
1296 'These files spam the console log with LOG(INFO):',
1297 items=log_info)]
1298 if printf:
1299 return [output_api.PresubmitError(
1300 'These files spam the console log with printf/fprintf:',
1301 items=printf)]
1302 return []
1303
1304
[email protected]49aa76a2013-12-04 06:59:161305def _CheckForAnonymousVariables(input_api, output_api):
1306 """These types are all expected to hold locks while in scope and
1307 so should never be anonymous (which causes them to be immediately
1308 destroyed)."""
1309 they_who_must_be_named = [
1310 'base::AutoLock',
1311 'base::AutoReset',
1312 'base::AutoUnlock',
1313 'SkAutoAlphaRestore',
1314 'SkAutoBitmapShaderInstall',
1315 'SkAutoBlitterChoose',
1316 'SkAutoBounderCommit',
1317 'SkAutoCallProc',
1318 'SkAutoCanvasRestore',
1319 'SkAutoCommentBlock',
1320 'SkAutoDescriptor',
1321 'SkAutoDisableDirectionCheck',
1322 'SkAutoDisableOvalCheck',
1323 'SkAutoFree',
1324 'SkAutoGlyphCache',
1325 'SkAutoHDC',
1326 'SkAutoLockColors',
1327 'SkAutoLockPixels',
1328 'SkAutoMalloc',
1329 'SkAutoMaskFreeImage',
1330 'SkAutoMutexAcquire',
1331 'SkAutoPathBoundsUpdate',
1332 'SkAutoPDFRelease',
1333 'SkAutoRasterClipValidate',
1334 'SkAutoRef',
1335 'SkAutoTime',
1336 'SkAutoTrace',
1337 'SkAutoUnref',
1338 ]
1339 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1340 # bad: base::AutoLock(lock.get());
1341 # not bad: base::AutoLock lock(lock.get());
1342 bad_pattern = input_api.re.compile(anonymous)
1343 # good: new base::AutoLock(lock.get())
1344 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1345 errors = []
1346
1347 for f in input_api.AffectedFiles():
1348 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1349 continue
1350 for linenum, line in f.ChangedContents():
1351 if bad_pattern.search(line) and not good_pattern.search(line):
1352 errors.append('%s:%d' % (f.LocalPath(), linenum))
1353
1354 if errors:
1355 return [output_api.PresubmitError(
1356 'These lines create anonymous variables that need to be named:',
1357 items=errors)]
1358 return []
1359
1360
[email protected]999261d2014-03-03 20:08:081361def _CheckUserActionUpdate(input_api, output_api):
1362 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521363 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081364 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521365 # If actions.xml is already included in the changelist, the PRESUBMIT
1366 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081367 return []
1368
[email protected]999261d2014-03-03 20:08:081369 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1370 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521371 current_actions = None
[email protected]999261d2014-03-03 20:08:081372 for f in input_api.AffectedFiles(file_filter=file_filter):
1373 for line_num, line in f.ChangedContents():
1374 match = input_api.re.search(action_re, line)
1375 if match:
[email protected]2f92dec2014-03-07 19:21:521376 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1377 # loaded only once.
1378 if not current_actions:
1379 with open('tools/metrics/actions/actions.xml') as actions_f:
1380 current_actions = actions_f.read()
1381 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081382 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521383 action = 'name="{0}"'.format(action_name)
1384 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081385 return [output_api.PresubmitPromptWarning(
1386 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521387 'tools/metrics/actions/actions.xml. Please run '
1388 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081389 % (f.LocalPath(), line_num, action_name))]
1390 return []
1391
1392
Daniel Cheng13ca61a882017-08-25 15:11:251393def _ImportJSONCommentEater(input_api):
1394 import sys
1395 sys.path = sys.path + [input_api.os_path.join(
1396 input_api.PresubmitLocalPath(),
1397 'tools', 'json_comment_eater')]
1398 import json_comment_eater
1399 return json_comment_eater
1400
1401
[email protected]99171a92014-06-03 08:44:471402def _GetJSONParseError(input_api, filename, eat_comments=True):
1403 try:
1404 contents = input_api.ReadFile(filename)
1405 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251406 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131407 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471408
1409 input_api.json.loads(contents)
1410 except ValueError as e:
1411 return e
1412 return None
1413
1414
1415def _GetIDLParseError(input_api, filename):
1416 try:
1417 contents = input_api.ReadFile(filename)
1418 idl_schema = input_api.os_path.join(
1419 input_api.PresubmitLocalPath(),
1420 'tools', 'json_schema_compiler', 'idl_schema.py')
1421 process = input_api.subprocess.Popen(
1422 [input_api.python_executable, idl_schema],
1423 stdin=input_api.subprocess.PIPE,
1424 stdout=input_api.subprocess.PIPE,
1425 stderr=input_api.subprocess.PIPE,
1426 universal_newlines=True)
1427 (_, error) = process.communicate(input=contents)
1428 return error or None
1429 except ValueError as e:
1430 return e
1431
1432
1433def _CheckParseErrors(input_api, output_api):
1434 """Check that IDL and JSON files do not contain syntax errors."""
1435 actions = {
1436 '.idl': _GetIDLParseError,
1437 '.json': _GetJSONParseError,
1438 }
[email protected]99171a92014-06-03 08:44:471439 # Most JSON files are preprocessed and support comments, but these do not.
1440 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491441 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471442 ]
1443 # Only run IDL checker on files in these directories.
1444 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491445 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1446 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471447 ]
1448
1449 def get_action(affected_file):
1450 filename = affected_file.LocalPath()
1451 return actions.get(input_api.os_path.splitext(filename)[1])
1452
[email protected]99171a92014-06-03 08:44:471453 def FilterFile(affected_file):
1454 action = get_action(affected_file)
1455 if not action:
1456 return False
1457 path = affected_file.LocalPath()
1458
Sean Kau46e29bc2017-08-28 16:31:161459 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471460 return False
1461
1462 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161463 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471464 return False
1465 return True
1466
1467 results = []
1468 for affected_file in input_api.AffectedFiles(
1469 file_filter=FilterFile, include_deletes=False):
1470 action = get_action(affected_file)
1471 kwargs = {}
1472 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161473 _MatchesFile(input_api, json_no_comments_patterns,
1474 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471475 kwargs['eat_comments'] = False
1476 parse_error = action(input_api,
1477 affected_file.AbsoluteLocalPath(),
1478 **kwargs)
1479 if parse_error:
1480 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1481 (affected_file.LocalPath(), parse_error)))
1482 return results
1483
1484
[email protected]760deea2013-12-10 19:33:491485def _CheckJavaStyle(input_api, output_api):
1486 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471487 import sys
[email protected]760deea2013-12-10 19:33:491488 original_sys_path = sys.path
1489 try:
1490 sys.path = sys.path + [input_api.os_path.join(
1491 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1492 import checkstyle
1493 finally:
1494 # Restore sys.path to what it was before.
1495 sys.path = original_sys_path
1496
1497 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091498 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511499 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491500
1501
Sean Kau46e29bc2017-08-28 16:31:161502def _MatchesFile(input_api, patterns, path):
1503 for pattern in patterns:
1504 if input_api.re.search(pattern, path):
1505 return True
1506 return False
1507
1508
dchenge07de812016-06-20 19:27:171509def _CheckIpcOwners(input_api, output_api):
1510 """Checks that affected files involving IPC have an IPC OWNERS rule.
1511
1512 Whether or not a file affects IPC is determined by a simple whitelist of
1513 filename patterns."""
1514 file_patterns = [
palmerb19a0932017-01-24 04:00:311515 # Legacy IPC:
dchenge07de812016-06-20 19:27:171516 '*_messages.cc',
1517 '*_messages*.h',
1518 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311519 # Mojo IPC:
dchenge07de812016-06-20 19:27:171520 '*.mojom',
1521 '*_struct_traits*.*',
1522 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311523 '*.typemap',
1524 # Android native IPC:
1525 '*.aidl',
1526 # Blink uses a different file naming convention:
1527 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171528 '*StructTraits*.*',
1529 '*TypeConverter*.*',
1530 ]
1531
scottmg7a6ed5ba2016-11-04 18:22:041532 # These third_party directories do not contain IPCs, but contain files
1533 # matching the above patterns, which trigger false positives.
1534 exclude_paths = [
1535 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291536 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041537 ]
1538
dchenge07de812016-06-20 19:27:171539 # Dictionary mapping an OWNERS file path to Patterns.
1540 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1541 # rules ) to a PatternEntry.
1542 # PatternEntry is a dictionary with two keys:
1543 # - 'files': the files that are matched by this pattern
1544 # - 'rules': the per-file rules needed for this pattern
1545 # For example, if we expect OWNERS file to contain rules for *.mojom and
1546 # *_struct_traits*.*, Patterns might look like this:
1547 # {
1548 # '*.mojom': {
1549 # 'files': ...,
1550 # 'rules': [
1551 # 'per-file *.mojom=set noparent',
1552 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1553 # ],
1554 # },
1555 # '*_struct_traits*.*': {
1556 # 'files': ...,
1557 # 'rules': [
1558 # 'per-file *_struct_traits*.*=set noparent',
1559 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1560 # ],
1561 # },
1562 # }
1563 to_check = {}
1564
Daniel Cheng13ca61a882017-08-25 15:11:251565 def AddPatternToCheck(input_file, pattern):
1566 owners_file = input_api.os_path.join(
1567 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1568 if owners_file not in to_check:
1569 to_check[owners_file] = {}
1570 if pattern not in to_check[owners_file]:
1571 to_check[owners_file][pattern] = {
1572 'files': [],
1573 'rules': [
1574 'per-file %s=set noparent' % pattern,
1575 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1576 ]
1577 }
1578 to_check[owners_file][pattern]['files'].append(f)
1579
dchenge07de812016-06-20 19:27:171580 # Iterate through the affected files to see what we actually need to check
1581 # for. We should only nag patch authors about per-file rules if a file in that
1582 # directory would match that pattern. If a directory only contains *.mojom
1583 # files and no *_messages*.h files, we should only nag about rules for
1584 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251585 for f in input_api.AffectedFiles(include_deletes=False):
1586 # Manifest files don't have a strong naming convention. Instead, scan
1587 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161588 if (f.LocalPath().endswith('.json') and
1589 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1590 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251591 json_comment_eater = _ImportJSONCommentEater(input_api)
1592 mostly_json_lines = '\n'.join(f.NewContents())
1593 # Comments aren't allowed in strict JSON, so filter them out.
1594 json_lines = json_comment_eater.Nom(mostly_json_lines)
1595 json_content = input_api.json.loads(json_lines)
1596 if 'interface_provider_specs' in json_content:
1597 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171598 for pattern in file_patterns:
1599 if input_api.fnmatch.fnmatch(
1600 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041601 skip = False
1602 for exclude in exclude_paths:
1603 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1604 skip = True
1605 break
1606 if skip:
1607 continue
Daniel Cheng13ca61a882017-08-25 15:11:251608 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171609 break
1610
1611 # Now go through the OWNERS files we collected, filtering out rules that are
1612 # already present in that OWNERS file.
1613 for owners_file, patterns in to_check.iteritems():
1614 try:
1615 with file(owners_file) as f:
1616 lines = set(f.read().splitlines())
1617 for entry in patterns.itervalues():
1618 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1619 ]
1620 except IOError:
1621 # No OWNERS file, so all the rules are definitely missing.
1622 continue
1623
1624 # All the remaining lines weren't found in OWNERS files, so emit an error.
1625 errors = []
1626 for owners_file, patterns in to_check.iteritems():
1627 missing_lines = []
1628 files = []
1629 for pattern, entry in patterns.iteritems():
1630 missing_lines.extend(entry['rules'])
1631 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1632 if missing_lines:
1633 errors.append(
Daniel Cheng52111692017-06-14 08:00:591634 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171635 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1636
1637 results = []
1638 if errors:
vabrf5ce3bf92016-07-11 14:52:411639 if input_api.is_committing:
1640 output = output_api.PresubmitError
1641 else:
1642 output = output_api.PresubmitPromptWarning
1643 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591644 'Found OWNERS files that need to be updated for IPC security ' +
1645 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171646 long_text='\n\n'.join(errors)))
1647
1648 return results
1649
1650
jbriance9e12f162016-11-25 07:57:501651def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311652 """Checks that added or removed lines in non third party affected
1653 header files do not lead to new useless class or struct forward
1654 declaration.
jbriance9e12f162016-11-25 07:57:501655 """
1656 results = []
1657 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1658 input_api.re.MULTILINE)
1659 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1660 input_api.re.MULTILINE)
1661 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311662 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191663 not f.LocalPath().startswith('third_party/blink') and
1664 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311665 not f.LocalPath().startswith('third_party/WebKit') and
1666 not f.LocalPath().startswith('third_party\\WebKit')):
1667 continue
1668
jbriance9e12f162016-11-25 07:57:501669 if not f.LocalPath().endswith('.h'):
1670 continue
1671
1672 contents = input_api.ReadFile(f)
1673 fwd_decls = input_api.re.findall(class_pattern, contents)
1674 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1675
1676 useless_fwd_decls = []
1677 for decl in fwd_decls:
1678 count = sum(1 for _ in input_api.re.finditer(
1679 r'\b%s\b' % input_api.re.escape(decl), contents))
1680 if count == 1:
1681 useless_fwd_decls.append(decl)
1682
1683 if not useless_fwd_decls:
1684 continue
1685
1686 for line in f.GenerateScmDiff().splitlines():
1687 if (line.startswith('-') and not line.startswith('--') or
1688 line.startswith('+') and not line.startswith('++')):
1689 for decl in useless_fwd_decls:
1690 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1691 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241692 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501693 (f.LocalPath(), decl)))
1694 useless_fwd_decls.remove(decl)
1695
1696 return results
1697
1698
dskiba88634f4e2015-08-14 23:03:291699def _CheckAndroidToastUsage(input_api, output_api):
1700 """Checks that code uses org.chromium.ui.widget.Toast instead of
1701 android.widget.Toast (Chromium Toast doesn't force hardware
1702 acceleration on low-end devices, saving memory).
1703 """
1704 toast_import_pattern = input_api.re.compile(
1705 r'^import android\.widget\.Toast;$')
1706
1707 errors = []
1708
1709 sources = lambda affected_file: input_api.FilterSourceFile(
1710 affected_file,
1711 black_list=(_EXCLUDED_PATHS +
1712 _TEST_CODE_EXCLUDED_PATHS +
1713 input_api.DEFAULT_BLACK_LIST +
1714 (r'^chromecast[\\\/].*',
1715 r'^remoting[\\\/].*')),
1716 white_list=(r'.*\.java$',))
1717
1718 for f in input_api.AffectedSourceFiles(sources):
1719 for line_num, line in f.ChangedContents():
1720 if toast_import_pattern.search(line):
1721 errors.append("%s:%d" % (f.LocalPath(), line_num))
1722
1723 results = []
1724
1725 if errors:
1726 results.append(output_api.PresubmitError(
1727 'android.widget.Toast usage is detected. Android toasts use hardware'
1728 ' acceleration, and can be\ncostly on low-end devices. Please use'
1729 ' org.chromium.ui.widget.Toast instead.\n'
1730 'Contact [email protected] if you have any questions.',
1731 errors))
1732
1733 return results
1734
1735
dgnaa68d5e2015-06-10 10:08:221736def _CheckAndroidCrLogUsage(input_api, output_api):
1737 """Checks that new logs using org.chromium.base.Log:
1738 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511739 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221740 """
pkotwicza1dd0b002016-05-16 14:41:041741
torne89540622017-03-24 19:41:301742 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041743 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301744 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041745 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301746 # WebView license viewer code cannot depend on //base; used in stub APK.
1747 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1748 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041749 ]
1750
dgnaa68d5e2015-06-10 10:08:221751 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121752 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1753 class_in_base_pattern = input_api.re.compile(
1754 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1755 has_some_log_import_pattern = input_api.re.compile(
1756 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221757 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121758 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221759 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511760 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221761 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221762
Vincent Scheib16d7b272015-09-15 18:09:071763 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221764 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041765 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1766 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121767
dgnaa68d5e2015-06-10 10:08:221768 tag_decl_errors = []
1769 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121770 tag_errors = []
dgn38736db2015-09-18 19:20:511771 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121772 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221773
1774 for f in input_api.AffectedSourceFiles(sources):
1775 file_content = input_api.ReadFile(f)
1776 has_modified_logs = False
1777
1778 # Per line checks
dgn87d9fb62015-06-12 09:15:121779 if (cr_log_import_pattern.search(file_content) or
1780 (class_in_base_pattern.search(file_content) and
1781 not has_some_log_import_pattern.search(file_content))):
1782 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221783 for line_num, line in f.ChangedContents():
1784
1785 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121786 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221787 if match:
1788 has_modified_logs = True
1789
1790 # Make sure it uses "TAG"
1791 if not match.group('tag') == 'TAG':
1792 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121793 else:
1794 # Report non cr Log function calls in changed lines
1795 for line_num, line in f.ChangedContents():
1796 if log_call_pattern.search(line):
1797 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221798
1799 # Per file checks
1800 if has_modified_logs:
1801 # Make sure the tag is using the "cr" prefix and is not too long
1802 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511803 tag_name = match.group('name') if match else None
1804 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221805 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511806 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221807 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511808 elif '.' in tag_name:
1809 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221810
1811 results = []
1812 if tag_decl_errors:
1813 results.append(output_api.PresubmitPromptWarning(
1814 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511815 '"private static final String TAG = "<package tag>".\n'
1816 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221817 tag_decl_errors))
1818
1819 if tag_length_errors:
1820 results.append(output_api.PresubmitError(
1821 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511822 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221823 tag_length_errors))
1824
1825 if tag_errors:
1826 results.append(output_api.PresubmitPromptWarning(
1827 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1828 tag_errors))
1829
dgn87d9fb62015-06-12 09:15:121830 if util_log_errors:
dgn4401aa52015-04-29 16:26:171831 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121832 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1833 util_log_errors))
1834
dgn38736db2015-09-18 19:20:511835 if tag_with_dot_errors:
1836 results.append(output_api.PresubmitPromptWarning(
1837 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1838 tag_with_dot_errors))
1839
dgn4401aa52015-04-29 16:26:171840 return results
1841
1842
Yoland Yanb92fa522017-08-28 17:37:061843def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1844 """Checks that junit.framework.* is no longer used."""
1845 deprecated_junit_framework_pattern = input_api.re.compile(
1846 r'^import junit\.framework\..*;',
1847 input_api.re.MULTILINE)
1848 sources = lambda x: input_api.FilterSourceFile(
1849 x, white_list=(r'.*\.java$',), black_list=None)
1850 errors = []
1851 for f in input_api.AffectedFiles(sources):
1852 for line_num, line in f.ChangedContents():
1853 if deprecated_junit_framework_pattern.search(line):
1854 errors.append("%s:%d" % (f.LocalPath(), line_num))
1855
1856 results = []
1857 if errors:
1858 results.append(output_api.PresubmitError(
1859 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1860 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1861 ' if you have any question.', errors))
1862 return results
1863
1864
1865def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1866 """Checks that if new Java test classes have inheritance.
1867 Either the new test class is JUnit3 test or it is a JUnit4 test class
1868 with a base class, either case is undesirable.
1869 """
1870 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1871
1872 sources = lambda x: input_api.FilterSourceFile(
1873 x, white_list=(r'.*Test\.java$',), black_list=None)
1874 errors = []
1875 for f in input_api.AffectedFiles(sources):
1876 if not f.OldContents():
1877 class_declaration_start_flag = False
1878 for line_num, line in f.ChangedContents():
1879 if class_declaration_pattern.search(line):
1880 class_declaration_start_flag = True
1881 if class_declaration_start_flag and ' extends ' in line:
1882 errors.append('%s:%d' % (f.LocalPath(), line_num))
1883 if '{' in line:
1884 class_declaration_start_flag = False
1885
1886 results = []
1887 if errors:
1888 results.append(output_api.PresubmitPromptWarning(
1889 'The newly created files include Test classes that inherits from base'
1890 ' class. Please do not use inheritance in JUnit4 tests or add new'
1891 ' JUnit3 tests. Contact [email protected] if you have any'
1892 ' questions.', errors))
1893 return results
1894
yolandyan45001472016-12-21 21:12:421895def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1896 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1897 deprecated_annotation_import_pattern = input_api.re.compile(
1898 r'^import android\.test\.suitebuilder\.annotation\..*;',
1899 input_api.re.MULTILINE)
1900 sources = lambda x: input_api.FilterSourceFile(
1901 x, white_list=(r'.*\.java$',), black_list=None)
1902 errors = []
1903 for f in input_api.AffectedFiles(sources):
1904 for line_num, line in f.ChangedContents():
1905 if deprecated_annotation_import_pattern.search(line):
1906 errors.append("%s:%d" % (f.LocalPath(), line_num))
1907
1908 results = []
1909 if errors:
1910 results.append(output_api.PresubmitError(
1911 'Annotations in android.test.suitebuilder.annotation have been'
1912 ' deprecated since API level 24. Please use android.support.test.filters'
1913 ' from //third_party/android_support_test_runner:runner_java instead.'
1914 ' Contact [email protected] if you have any questions.', errors))
1915 return results
1916
1917
agrieve7b6479d82015-10-07 14:24:221918def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1919 """Checks if MDPI assets are placed in a correct directory."""
1920 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1921 ('/res/drawable/' in f.LocalPath() or
1922 '/res/drawable-ldrtl/' in f.LocalPath()))
1923 errors = []
1924 for f in input_api.AffectedFiles(include_deletes=False,
1925 file_filter=file_filter):
1926 errors.append(' %s' % f.LocalPath())
1927
1928 results = []
1929 if errors:
1930 results.append(output_api.PresubmitError(
1931 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1932 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1933 '/res/drawable-ldrtl/.\n'
1934 'Contact [email protected] if you have questions.', errors))
1935 return results
1936
1937
Nate Fischer535972b2017-09-16 01:06:181938def _CheckAndroidWebkitImports(input_api, output_api):
1939 """Checks that code uses org.chromium.base.Callback instead of
1940 android.widget.ValueCallback except in the WebView glue layer.
1941 """
1942 valuecallback_import_pattern = input_api.re.compile(
1943 r'^import android\.webkit\.ValueCallback;$')
1944
1945 errors = []
1946
1947 sources = lambda affected_file: input_api.FilterSourceFile(
1948 affected_file,
1949 black_list=(_EXCLUDED_PATHS +
1950 _TEST_CODE_EXCLUDED_PATHS +
1951 input_api.DEFAULT_BLACK_LIST +
1952 (r'^android_webview[\\\/]glue[\\\/].*',)),
1953 white_list=(r'.*\.java$',))
1954
1955 for f in input_api.AffectedSourceFiles(sources):
1956 for line_num, line in f.ChangedContents():
1957 if valuecallback_import_pattern.search(line):
1958 errors.append("%s:%d" % (f.LocalPath(), line_num))
1959
1960 results = []
1961
1962 if errors:
1963 results.append(output_api.PresubmitError(
1964 'android.webkit.ValueCallback usage is detected outside of the glue'
1965 ' layer. To stay compatible with the support library, android.webkit.*'
1966 ' classes should only be used inside the glue layer and'
1967 ' org.chromium.base.Callback should be used instead.',
1968 errors))
1969
1970 return results
1971
1972
agrievef32bcc72016-04-04 14:57:401973class PydepsChecker(object):
1974 def __init__(self, input_api, pydeps_files):
1975 self._file_cache = {}
1976 self._input_api = input_api
1977 self._pydeps_files = pydeps_files
1978
1979 def _LoadFile(self, path):
1980 """Returns the list of paths within a .pydeps file relative to //."""
1981 if path not in self._file_cache:
1982 with open(path) as f:
1983 self._file_cache[path] = f.read()
1984 return self._file_cache[path]
1985
1986 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1987 """Returns an interable of paths within the .pydep, relativized to //."""
1988 os_path = self._input_api.os_path
1989 pydeps_dir = os_path.dirname(pydeps_path)
1990 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1991 if not l.startswith('*'))
1992 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1993
1994 def _CreateFilesToPydepsMap(self):
1995 """Returns a map of local_path -> list_of_pydeps."""
1996 ret = {}
1997 for pydep_local_path in self._pydeps_files:
1998 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1999 ret.setdefault(path, []).append(pydep_local_path)
2000 return ret
2001
2002 def ComputeAffectedPydeps(self):
2003 """Returns an iterable of .pydeps files that might need regenerating."""
2004 affected_pydeps = set()
2005 file_to_pydeps_map = None
2006 for f in self._input_api.AffectedFiles(include_deletes=True):
2007 local_path = f.LocalPath()
2008 if local_path == 'DEPS':
2009 return self._pydeps_files
2010 elif local_path.endswith('.pydeps'):
2011 if local_path in self._pydeps_files:
2012 affected_pydeps.add(local_path)
2013 elif local_path.endswith('.py'):
2014 if file_to_pydeps_map is None:
2015 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2016 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2017 return affected_pydeps
2018
2019 def DetermineIfStale(self, pydeps_path):
2020 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412021 import difflib
agrievef32bcc72016-04-04 14:57:402022 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2023 cmd = old_pydeps_data[1][1:].strip()
2024 new_pydeps_data = self._input_api.subprocess.check_output(
2025 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:412026 old_contents = old_pydeps_data[2:]
2027 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402028 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412029 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402030
2031
2032def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2033 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:002034 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:282035 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
2036 # Mac, so skip it on other platforms.
2037 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002038 return []
agrievef32bcc72016-04-04 14:57:402039 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
2040 is_android = input_api.os_path.exists('third_party/android_tools')
2041 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2042 results = []
2043 # First, check for new / deleted .pydeps.
2044 for f in input_api.AffectedFiles(include_deletes=True):
2045 if f.LocalPath().endswith('.pydeps'):
2046 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2047 results.append(output_api.PresubmitError(
2048 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2049 'remove %s' % f.LocalPath()))
2050 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2051 results.append(output_api.PresubmitError(
2052 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2053 'include %s' % f.LocalPath()))
2054
2055 if results:
2056 return results
2057
2058 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2059
2060 for pydep_path in checker.ComputeAffectedPydeps():
2061 try:
phajdan.jr0d9878552016-11-04 10:49:412062 result = checker.DetermineIfStale(pydep_path)
2063 if result:
2064 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402065 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412066 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2067 'To regenerate, run:\n\n %s' %
2068 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402069 except input_api.subprocess.CalledProcessError as error:
2070 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2071 long_text=error.output)]
2072
2073 return results
2074
2075
glidere61efad2015-02-18 17:39:432076def _CheckSingletonInHeaders(input_api, output_api):
2077 """Checks to make sure no header files have |Singleton<|."""
2078 def FileFilter(affected_file):
2079 # It's ok for base/memory/singleton.h to have |Singleton<|.
2080 black_list = (_EXCLUDED_PATHS +
2081 input_api.DEFAULT_BLACK_LIST +
2082 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2083 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2084
sergeyu34d21222015-09-16 00:11:442085 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432086 files = []
2087 for f in input_api.AffectedSourceFiles(FileFilter):
2088 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2089 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2090 contents = input_api.ReadFile(f)
2091 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242092 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432093 pattern.search(line)):
2094 files.append(f)
2095 break
2096
2097 if files:
yolandyandaabc6d2016-04-18 18:29:392098 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442099 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432100 'Please move them to an appropriate source file so that the ' +
2101 'template gets instantiated in a single compilation unit.',
2102 files) ]
2103 return []
2104
2105
[email protected]fd20b902014-05-09 02:14:532106_DEPRECATED_CSS = [
2107 # Values
2108 ( "-webkit-box", "flex" ),
2109 ( "-webkit-inline-box", "inline-flex" ),
2110 ( "-webkit-flex", "flex" ),
2111 ( "-webkit-inline-flex", "inline-flex" ),
2112 ( "-webkit-min-content", "min-content" ),
2113 ( "-webkit-max-content", "max-content" ),
2114
2115 # Properties
2116 ( "-webkit-background-clip", "background-clip" ),
2117 ( "-webkit-background-origin", "background-origin" ),
2118 ( "-webkit-background-size", "background-size" ),
2119 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442120 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532121
2122 # Functions
2123 ( "-webkit-gradient", "gradient" ),
2124 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2125 ( "-webkit-linear-gradient", "linear-gradient" ),
2126 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2127 ( "-webkit-radial-gradient", "radial-gradient" ),
2128 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2129]
2130
dbeam1ec68ac2016-12-15 05:22:242131def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532132 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252133 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342134 documentation and iOS CSS for dom distiller
2135 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252136 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532137 results = []
dbeam070cfe62014-10-22 06:44:022138 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252139 black_list = (_EXCLUDED_PATHS +
2140 _TEST_CODE_EXCLUDED_PATHS +
2141 input_api.DEFAULT_BLACK_LIST +
2142 (r"^chrome/common/extensions/docs",
2143 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342144 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442145 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252146 r"^native_client_sdk"))
2147 file_filter = lambda f: input_api.FilterSourceFile(
2148 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532149 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2150 for line_num, line in fpath.ChangedContents():
2151 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022152 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532153 results.append(output_api.PresubmitError(
2154 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2155 (fpath.LocalPath(), line_num, deprecated_value, value)))
2156 return results
2157
mohan.reddyf21db962014-10-16 12:26:472158
dbeam070cfe62014-10-22 06:44:022159_DEPRECATED_JS = [
2160 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2161 ( "__defineGetter__", "Object.defineProperty" ),
2162 ( "__defineSetter__", "Object.defineProperty" ),
2163]
2164
dbeam1ec68ac2016-12-15 05:22:242165def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022166 """Make sure that we don't use deprecated JS in Chrome code."""
2167 results = []
2168 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2169 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2170 input_api.DEFAULT_BLACK_LIST)
2171 file_filter = lambda f: input_api.FilterSourceFile(
2172 f, white_list=file_inclusion_pattern, black_list=black_list)
2173 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2174 for lnum, line in fpath.ChangedContents():
2175 for (deprecated, replacement) in _DEPRECATED_JS:
2176 if deprecated in line:
2177 results.append(output_api.PresubmitError(
2178 "%s:%d: Use of deprecated JS %s, use %s instead" %
2179 (fpath.LocalPath(), lnum, deprecated, replacement)))
2180 return results
2181
dpapadd651231d82017-07-21 02:44:472182def _CheckForRiskyJsArrowFunction(line_number, line):
2183 if ' => ' in line:
2184 return "line %d, is using an => (arrow) function\n %s\n" % (
2185 line_number, line)
2186 return ''
2187
2188def _CheckForRiskyJsConstLet(input_api, line_number, line):
2189 if input_api.re.match('^\s*(const|let)\s', line):
2190 return "line %d, is using const/let keyword\n %s\n" % (
2191 line_number, line)
2192 return ''
dbeam070cfe62014-10-22 06:44:022193
dbeam1ec68ac2016-12-15 05:22:242194def _CheckForRiskyJsFeatures(input_api, output_api):
2195 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002196 # 'ui/webui/resources/cr_components are not allowed on ios'
2197 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572198 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002199 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472200 results = []
dbeam1ec68ac2016-12-15 05:22:242201 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472202 arrow_error_lines = []
2203 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242204 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472205 arrow_error_lines += filter(None, [
2206 _CheckForRiskyJsArrowFunction(lnum, line),
2207 ])
dbeam1ec68ac2016-12-15 05:22:242208
dpapadd651231d82017-07-21 02:44:472209 const_let_error_lines += filter(None, [
2210 _CheckForRiskyJsConstLet(input_api, lnum, line),
2211 ])
dbeam1ec68ac2016-12-15 05:22:242212
dpapadd651231d82017-07-21 02:44:472213 if arrow_error_lines:
2214 arrow_error_lines = map(
2215 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2216 results.append(
2217 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2218"""
2219Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242220%s
2221Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2222https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472223""" % f.LocalPath()
2224 ])))
dbeam1ec68ac2016-12-15 05:22:242225
dpapadd651231d82017-07-21 02:44:472226 if const_let_error_lines:
2227 const_let_error_lines = map(
2228 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2229 results.append(
2230 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2231"""
2232Use of const/let keywords detected in:
2233%s
2234Please ensure your code does not run on iOS9 because const/let is not fully
2235supported.
2236https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2237https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2238""" % f.LocalPath()
2239 ])))
2240
2241 return results
dbeam1ec68ac2016-12-15 05:22:242242
rlanday6802cf632017-05-30 17:48:362243def _CheckForRelativeIncludes(input_api, output_api):
2244 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2245 import sys
2246 original_sys_path = sys.path
2247 try:
2248 sys.path = sys.path + [input_api.os_path.join(
2249 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2250 from cpp_checker import CppChecker
2251 finally:
2252 # Restore sys.path to what it was before.
2253 sys.path = original_sys_path
2254
2255 bad_files = {}
2256 for f in input_api.AffectedFiles(include_deletes=False):
2257 if (f.LocalPath().startswith('third_party') and
2258 not f.LocalPath().startswith('third_party/WebKit') and
2259 not f.LocalPath().startswith('third_party\\WebKit')):
2260 continue
2261
2262 if not CppChecker.IsCppFile(f.LocalPath()):
2263 continue
2264
2265 relative_includes = [line for line_num, line in f.ChangedContents()
2266 if "#include" in line and "../" in line]
2267 if not relative_includes:
2268 continue
2269 bad_files[f.LocalPath()] = relative_includes
2270
2271 if not bad_files:
2272 return []
2273
2274 error_descriptions = []
2275 for file_path, bad_lines in bad_files.iteritems():
2276 error_description = file_path
2277 for line in bad_lines:
2278 error_description += '\n ' + line
2279 error_descriptions.append(error_description)
2280
2281 results = []
2282 results.append(output_api.PresubmitError(
2283 'You added one or more relative #include paths (including "../").\n'
2284 'These shouldn\'t be used because they can be used to include headers\n'
2285 'from code that\'s not correctly specified as a dependency in the\n'
2286 'relevant BUILD.gn file(s).',
2287 error_descriptions))
2288
2289 return results
2290
Takeshi Yoshinoe387aa32017-08-02 13:16:132291
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202292def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2293 if not isinstance(key, ast.Str):
2294 return 'Key at line %d must be a string literal' % key.lineno
2295 if not isinstance(value, ast.Dict):
2296 return 'Value at line %d must be a dict' % value.lineno
2297 if len(value.keys) != 1:
2298 return 'Dict at line %d must have single entry' % value.lineno
2299 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2300 return (
2301 'Entry at line %d must have a string literal \'filepath\' as key' %
2302 value.lineno)
2303 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132304
Takeshi Yoshinoe387aa32017-08-02 13:16:132305
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202306def _CheckWatchlistsEntrySyntax(key, value, ast):
2307 if not isinstance(key, ast.Str):
2308 return 'Key at line %d must be a string literal' % key.lineno
2309 if not isinstance(value, ast.List):
2310 return 'Value at line %d must be a list' % value.lineno
2311 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132312
Takeshi Yoshinoe387aa32017-08-02 13:16:132313
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202314def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2315 mismatch_template = (
2316 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2317 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132318
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202319 i = 0
2320 last_key = ''
2321 while True:
2322 if i >= len(wd_dict.keys):
2323 if i >= len(w_dict.keys):
2324 return None
2325 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2326 elif i >= len(w_dict.keys):
2327 return (
2328 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132329
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202330 wd_key = wd_dict.keys[i]
2331 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132332
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202333 result = _CheckWatchlistDefinitionsEntrySyntax(
2334 wd_key, wd_dict.values[i], ast)
2335 if result is not None:
2336 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132337
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202338 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2339 if result is not None:
2340 return 'Bad entry in WATCHLISTS dict: %s' % result
2341
2342 if wd_key.s != w_key.s:
2343 return mismatch_template % (
2344 '%s at line %d' % (wd_key.s, wd_key.lineno),
2345 '%s at line %d' % (w_key.s, w_key.lineno))
2346
2347 if wd_key.s < last_key:
2348 return (
2349 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2350 (wd_key.lineno, w_key.lineno))
2351 last_key = wd_key.s
2352
2353 i = i + 1
2354
2355
2356def _CheckWATCHLISTSSyntax(expression, ast):
2357 if not isinstance(expression, ast.Expression):
2358 return 'WATCHLISTS file must contain a valid expression'
2359 dictionary = expression.body
2360 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2361 return 'WATCHLISTS file must have single dict with exactly two entries'
2362
2363 first_key = dictionary.keys[0]
2364 first_value = dictionary.values[0]
2365 second_key = dictionary.keys[1]
2366 second_value = dictionary.values[1]
2367
2368 if (not isinstance(first_key, ast.Str) or
2369 first_key.s != 'WATCHLIST_DEFINITIONS' or
2370 not isinstance(first_value, ast.Dict)):
2371 return (
2372 'The first entry of the dict in WATCHLISTS file must be '
2373 'WATCHLIST_DEFINITIONS dict')
2374
2375 if (not isinstance(second_key, ast.Str) or
2376 second_key.s != 'WATCHLISTS' or
2377 not isinstance(second_value, ast.Dict)):
2378 return (
2379 'The second entry of the dict in WATCHLISTS file must be '
2380 'WATCHLISTS dict')
2381
2382 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132383
2384
2385def _CheckWATCHLISTS(input_api, output_api):
2386 for f in input_api.AffectedFiles(include_deletes=False):
2387 if f.LocalPath() == 'WATCHLISTS':
2388 contents = input_api.ReadFile(f, 'r')
2389
2390 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202391 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132392 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202393 # Get an AST tree for it and scan the tree for detailed style checking.
2394 expression = input_api.ast.parse(
2395 contents, filename='WATCHLISTS', mode='eval')
2396 except ValueError as e:
2397 return [output_api.PresubmitError(
2398 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2399 except SyntaxError as e:
2400 return [output_api.PresubmitError(
2401 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2402 except TypeError as e:
2403 return [output_api.PresubmitError(
2404 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132405
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202406 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2407 if result is not None:
2408 return [output_api.PresubmitError(result)]
2409 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132410
2411 return []
2412
2413
dgnaa68d5e2015-06-10 10:08:222414def _AndroidSpecificOnUploadChecks(input_api, output_api):
2415 """Groups checks that target android code."""
2416 results = []
dgnaa68d5e2015-06-10 10:08:222417 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222418 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292419 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062420 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2421 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422422 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182423 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222424 return results
2425
2426
[email protected]22c9bd72011-03-27 16:47:392427def _CommonChecks(input_api, output_api):
2428 """Checks common to both upload and commit."""
2429 results = []
2430 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382431 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542432 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582433 results.extend(
2434 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192435 results.extend(
[email protected]760deea2013-12-10 19:33:492436 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542437 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182438 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522439 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222440 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442441 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592442 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062443 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122444 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182445 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222446 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302447 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492448 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032449 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492450 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442451 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272452 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072453 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542454 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442455 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392456 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552457 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042458 results.extend(
2459 input_api.canned_checks.CheckChangeHasNoTabs(
2460 input_api,
2461 output_api,
2462 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402463 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162464 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082465 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242466 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2467 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472468 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042469 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232470 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432471 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402472 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152473 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172474 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502475 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242476 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362477 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132478 results.extend(_CheckWATCHLISTS(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242479
2480 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2481 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2482 input_api, output_api,
2483 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382484 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392485 return results
[email protected]1f7b4172010-01-28 01:17:342486
[email protected]b337cb5b2011-01-23 21:24:052487
[email protected]b8079ae4a2012-12-05 19:56:492488def _CheckPatchFiles(input_api, output_api):
2489 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2490 if f.LocalPath().endswith(('.orig', '.rej'))]
2491 if problems:
2492 return [output_api.PresubmitError(
2493 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032494 else:
2495 return []
[email protected]b8079ae4a2012-12-05 19:56:492496
2497
Kent Tamura5a8755d2017-06-29 23:37:072498def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212499 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2500 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2501 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072502 include_re = input_api.re.compile(
2503 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2504 extension_re = input_api.re.compile(r'\.[a-z]+$')
2505 errors = []
2506 for f in input_api.AffectedFiles():
2507 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2508 continue
2509 found_line_number = None
2510 found_macro = None
2511 for line_num, line in f.ChangedContents():
2512 match = macro_re.search(line)
2513 if match:
2514 found_line_number = line_num
2515 found_macro = match.group(2)
2516 break
2517 if not found_line_number:
2518 continue
2519
2520 found_include = False
2521 for line in f.NewContents():
2522 if include_re.search(line):
2523 found_include = True
2524 break
2525 if found_include:
2526 continue
2527
2528 if not f.LocalPath().endswith('.h'):
2529 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2530 try:
2531 content = input_api.ReadFile(primary_header_path, 'r')
2532 if include_re.search(content):
2533 continue
2534 except IOError:
2535 pass
2536 errors.append('%s:%d %s macro is used without including build/'
2537 'build_config.h.'
2538 % (f.LocalPath(), found_line_number, found_macro))
2539 if errors:
2540 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2541 return []
2542
2543
[email protected]b00342e7f2013-03-26 16:21:542544def _DidYouMeanOSMacro(bad_macro):
2545 try:
2546 return {'A': 'OS_ANDROID',
2547 'B': 'OS_BSD',
2548 'C': 'OS_CHROMEOS',
2549 'F': 'OS_FREEBSD',
2550 'L': 'OS_LINUX',
2551 'M': 'OS_MACOSX',
2552 'N': 'OS_NACL',
2553 'O': 'OS_OPENBSD',
2554 'P': 'OS_POSIX',
2555 'S': 'OS_SOLARIS',
2556 'W': 'OS_WIN'}[bad_macro[3].upper()]
2557 except KeyError:
2558 return ''
2559
2560
2561def _CheckForInvalidOSMacrosInFile(input_api, f):
2562 """Check for sensible looking, totally invalid OS macros."""
2563 preprocessor_statement = input_api.re.compile(r'^\s*#')
2564 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2565 results = []
2566 for lnum, line in f.ChangedContents():
2567 if preprocessor_statement.search(line):
2568 for match in os_macro.finditer(line):
2569 if not match.group(1) in _VALID_OS_MACROS:
2570 good = _DidYouMeanOSMacro(match.group(1))
2571 did_you_mean = ' (did you mean %s?)' % good if good else ''
2572 results.append(' %s:%d %s%s' % (f.LocalPath(),
2573 lnum,
2574 match.group(1),
2575 did_you_mean))
2576 return results
2577
2578
2579def _CheckForInvalidOSMacros(input_api, output_api):
2580 """Check all affected files for invalid OS macros."""
2581 bad_macros = []
2582 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472583 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542584 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2585
2586 if not bad_macros:
2587 return []
2588
2589 return [output_api.PresubmitError(
2590 'Possibly invalid OS macro[s] found. Please fix your code\n'
2591 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2592
lliabraa35bab3932014-10-01 12:16:442593
2594def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2595 """Check all affected files for invalid "if defined" macros."""
2596 ALWAYS_DEFINED_MACROS = (
2597 "TARGET_CPU_PPC",
2598 "TARGET_CPU_PPC64",
2599 "TARGET_CPU_68K",
2600 "TARGET_CPU_X86",
2601 "TARGET_CPU_ARM",
2602 "TARGET_CPU_MIPS",
2603 "TARGET_CPU_SPARC",
2604 "TARGET_CPU_ALPHA",
2605 "TARGET_IPHONE_SIMULATOR",
2606 "TARGET_OS_EMBEDDED",
2607 "TARGET_OS_IPHONE",
2608 "TARGET_OS_MAC",
2609 "TARGET_OS_UNIX",
2610 "TARGET_OS_WIN32",
2611 )
2612 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2613 results = []
2614 for lnum, line in f.ChangedContents():
2615 for match in ifdef_macro.finditer(line):
2616 if match.group(1) in ALWAYS_DEFINED_MACROS:
2617 always_defined = ' %s is always defined. ' % match.group(1)
2618 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2619 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2620 lnum,
2621 always_defined,
2622 did_you_mean))
2623 return results
2624
2625
2626def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2627 """Check all affected files for invalid "if defined" macros."""
2628 bad_macros = []
2629 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212630 if f.LocalPath().startswith('third_party/sqlite/'):
2631 continue
lliabraa35bab3932014-10-01 12:16:442632 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2633 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2634
2635 if not bad_macros:
2636 return []
2637
2638 return [output_api.PresubmitError(
2639 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2640 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2641 bad_macros)]
2642
2643
mlamouria82272622014-09-16 18:45:042644def _CheckForIPCRules(input_api, output_api):
2645 """Check for same IPC rules described in
2646 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2647 """
2648 base_pattern = r'IPC_ENUM_TRAITS\('
2649 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2650 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2651
2652 problems = []
2653 for f in input_api.AffectedSourceFiles(None):
2654 local_path = f.LocalPath()
2655 if not local_path.endswith('.h'):
2656 continue
2657 for line_number, line in f.ChangedContents():
2658 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2659 problems.append(
2660 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2661
2662 if problems:
2663 return [output_api.PresubmitPromptWarning(
2664 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2665 else:
2666 return []
2667
[email protected]b00342e7f2013-03-26 16:21:542668
mostynbb639aca52015-01-07 20:31:232669def _CheckForWindowsLineEndings(input_api, output_api):
2670 """Check source code and known ascii text files for Windows style line
2671 endings.
2672 """
earthdok1b5e0ee2015-03-10 15:19:102673 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232674
2675 file_inclusion_pattern = (
2676 known_text_files,
2677 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2678 )
2679
2680 filter = lambda f: input_api.FilterSourceFile(
2681 f, white_list=file_inclusion_pattern, black_list=None)
2682 files = [f.LocalPath() for f in
2683 input_api.AffectedSourceFiles(filter)]
2684
2685 problems = []
2686
2687 for file in files:
2688 fp = open(file, 'r')
2689 for line in fp:
2690 if line.endswith('\r\n'):
2691 problems.append(file)
2692 break
2693 fp.close()
2694
2695 if problems:
2696 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2697 'these files to contain Windows style line endings?\n' +
2698 '\n'.join(problems))]
2699
2700 return []
2701
2702
pastarmovj89f7ee12016-09-20 14:58:132703def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2704 lint_filters=None, verbose_level=None):
2705 """Checks that all source files use SYSLOG properly."""
2706 syslog_files = []
2707 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562708 for line_number, line in f.ChangedContents():
2709 if 'SYSLOG' in line:
2710 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2711
pastarmovj89f7ee12016-09-20 14:58:132712 if syslog_files:
2713 return [output_api.PresubmitPromptWarning(
2714 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2715 ' calls.\nFiles to check:\n', items=syslog_files)]
2716 return []
2717
2718
[email protected]1f7b4172010-01-28 01:17:342719def CheckChangeOnUpload(input_api, output_api):
2720 results = []
2721 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472722 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282723 results.extend(
jam93a6ee792017-02-08 23:59:222724 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192725 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222726 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132727 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162728 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542729 return results
[email protected]ca8d1982009-02-19 16:33:122730
2731
[email protected]1bfb8322014-04-23 01:02:412732def GetTryServerMasterForBot(bot):
2733 """Returns the Try Server master for the given bot.
2734
[email protected]0bb112362014-07-26 04:38:322735 It tries to guess the master from the bot name, but may still fail
2736 and return None. There is no longer a default master.
2737 """
2738 # Potentially ambiguous bot names are listed explicitly.
2739 master_map = {
tandriie5587792016-07-14 00:34:502740 'chromium_presubmit': 'master.tryserver.chromium.linux',
2741 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412742 }
[email protected]0bb112362014-07-26 04:38:322743 master = master_map.get(bot)
2744 if not master:
wnwen4fbaab82016-05-25 12:54:362745 if 'android' in bot:
tandriie5587792016-07-14 00:34:502746 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362747 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502748 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322749 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502750 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322751 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502752 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322753 return master
[email protected]1bfb8322014-04-23 01:02:412754
2755
[email protected]ca8d1982009-02-19 16:33:122756def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542757 results = []
[email protected]1f7b4172010-01-28 01:17:342758 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542759 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272760 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342761 input_api,
2762 output_api,
[email protected]2fdd1f362013-01-16 03:56:032763 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272764
jam93a6ee792017-02-08 23:59:222765 results.extend(
2766 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542767 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2768 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412769 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2770 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542771 return results