blob: efd126db47336619586dcbb7fd390fd06f48a2d7 [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]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
Kent Tamurae9b3a9ec2017-08-31 02:20:1919 r"^third_party[\\\/](WebKit|blink)[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
vapierb2053f542017-03-09 19:46:1026 r"tools[\\\/]md_browser[\\\/].*\.css$",
ehmaldonado78eee2ed2017-03-28 13:16:5427 # Test pages for WebRTC telemetry tests.
28 r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4029)
[email protected]ca8d1982009-02-19 16:33:1230
wnwenbdc444e2016-05-25 13:44:1531
[email protected]06e6d0ff2012-12-11 01:36:4432# Fragment of a regular expression that matches C++ and Objective-C++
33# implementation files.
34_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
35
wnwenbdc444e2016-05-25 13:44:1536
[email protected]06e6d0ff2012-12-11 01:36:4437# Regular expression that matches code only used for test binaries
38# (best effort).
39_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4940 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4441 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
sdefresne1fccb0a2016-12-19 08:10:5342 r'.+_(api|browser|eg|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1243 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4444 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4945 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0546 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4947 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4748 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4949 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0850 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4951 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4452)
[email protected]ca8d1982009-02-19 16:33:1253
wnwenbdc444e2016-05-25 13:44:1554
[email protected]eea609a2011-11-18 13:10:1255_TEST_ONLY_WARNING = (
56 'You might be calling functions intended only for testing from\n'
57 'production code. It is OK to ignore this warning if you know what\n'
58 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5859 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1260
61
[email protected]cf9b78f2012-11-14 11:40:2862_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4063 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2164 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
65 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2866
wnwenbdc444e2016-05-25 13:44:1567
Eric Stevensona9a980972017-09-23 00:04:4168_BANNED_JAVA_FUNCTIONS = (
69 (
70 'StrictMode.allowThreadDiskReads()',
71 (
72 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
73 'directly.',
74 ),
75 False,
76 ),
77 (
78 'StrictMode.allowThreadDiskWrites()',
79 (
80 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
81 'directly.',
82 ),
83 False,
84 ),
85)
86
[email protected]127f18ec2012-06-16 05:05:5987_BANNED_OBJC_FUNCTIONS = (
88 (
89 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2090 (
91 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5992 'prohibited. Please use CrTrackingArea instead.',
93 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
94 ),
95 False,
96 ),
97 (
[email protected]eaae1972014-04-16 04:17:2698 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2099 (
100 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59101 'instead.',
102 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
103 ),
104 False,
105 ),
106 (
107 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20108 (
109 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59110 'Please use |convertPoint:(point) fromView:nil| instead.',
111 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
112 ),
113 True,
114 ),
115 (
116 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20117 (
118 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59119 'Please use |convertPoint:(point) toView:nil| instead.',
120 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
121 ),
122 True,
123 ),
124 (
125 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20126 (
127 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59128 'Please use |convertRect:(point) fromView:nil| instead.',
129 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
130 ),
131 True,
132 ),
133 (
134 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20135 (
136 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59137 'Please use |convertRect:(point) toView:nil| instead.',
138 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
139 ),
140 True,
141 ),
142 (
143 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20144 (
145 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59146 'Please use |convertSize:(point) fromView:nil| instead.',
147 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
148 ),
149 True,
150 ),
151 (
152 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20153 (
154 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59155 'Please use |convertSize:(point) toView:nil| instead.',
156 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
157 ),
158 True,
159 ),
jif65398702016-10-27 10:19:48160 (
161 r"/\s+UTF8String\s*]",
162 (
163 'The use of -[NSString UTF8String] is dangerous as it can return null',
164 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
165 'Please use |SysNSStringToUTF8| instead.',
166 ),
167 True,
168 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34169 (
170 r'__unsafe_unretained',
171 (
172 'The use of __unsafe_unretained is almost certainly wrong, unless',
173 'when interacting with NSFastEnumeration or NSInvocation.',
174 'Please use __weak in files build with ARC, nothing otherwise.',
175 ),
176 False,
177 ),
[email protected]127f18ec2012-06-16 05:05:59178)
179
180
181_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20182 # Make sure that gtest's FRIEND_TEST() macro is not used; the
183 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30184 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20185 (
thomasandersone7caaa9b2017-03-29 19:22:53186 r'\bNULL\b',
187 (
188 'New code should not use NULL. Use nullptr instead.',
189 ),
190 True,
191 (),
192 ),
193 (
[email protected]23e6cbc2012-06-16 18:51:20194 'FRIEND_TEST(',
195 (
[email protected]e3c945502012-06-26 20:01:49196 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20197 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
198 ),
199 False,
[email protected]7345da02012-11-27 14:31:49200 (),
[email protected]23e6cbc2012-06-16 18:51:20201 ),
202 (
thomasanderson4b569052016-09-14 20:15:53203 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
204 (
205 'Chrome clients wishing to select events on X windows should use',
206 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
207 'you are selecting events from the GPU process, or if you are using',
208 'an XDisplay other than gfx::GetXDisplay().',
209 ),
210 True,
211 (
212 r"^ui[\\\/]gl[\\\/].*\.cc$",
213 r"^media[\\\/]gpu[\\\/].*\.cc$",
214 r"^gpu[\\\/].*\.cc$",
215 ),
216 ),
217 (
thomasandersone043e3ce2017-06-08 00:43:20218 r'XInternAtom|xcb_intern_atom',
219 (
thomasanderson11aa41dc2017-06-08 22:22:38220 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20221 ),
222 True,
223 (
thomasanderson11aa41dc2017-06-08 22:22:38224 r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$",
225 r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20226 r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$",
227 ),
228 ),
229 (
[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 (
Chris Mumford13f84c72017-09-22 21:46:10432 'leveldb::NewMemEnv',
433 (
434 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
435 'third_party/leveldatabase/leveldb_chrome.h.',
436 ),
437 True,
438 (
439 r'^third_party/leveldatabase/.*\.(cc|h)$',
440 ),
441 ),
442 (
Gabriel Charetted9839bc2017-07-29 14:17:47443 'MessageLoop::QuitWhenIdleClosure',
Gabriel Charette0592c3a2017-07-26 12:02:04444 (
Robert Liao64b7ab22017-08-04 23:03:43445 'MessageLoop::QuitWhenIdleClosure is deprecated. Please migrate to',
446 'Runloop.',
Gabriel Charette0592c3a2017-07-26 12:02:04447 ),
448 True,
449 (),
Gabriel Charetted9839bc2017-07-29 14:17:47450 ),
451 (
452 'RunLoop::QuitCurrent',
453 (
Robert Liao64b7ab22017-08-04 23:03:43454 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
455 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47456 ),
457 True,
458 (),
Gabriel Charettea44975052017-08-21 23:14:04459 ),
460 (
461 'base::ScopedMockTimeMessageLoopTaskRunner',
462 (
463 'ScopedMockTimeMessageLoopTaskRunner is deprecated.',
464 ),
465 True,
466 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57467 ),
468 (
469 r'std::regex',
470 (
471 'Using std::regex adds unnecessary binary size to Chrome. Please use',
472 're2::RE2 instead (crbug/755321)',
473 ),
474 True,
475 (),
dskiba1474c2bfd62017-07-20 02:19:24476 )
[email protected]127f18ec2012-06-16 05:05:59477)
478
wnwenbdc444e2016-05-25 13:44:15479
mlamouria82272622014-09-16 18:45:04480_IPC_ENUM_TRAITS_DEPRECATED = (
481 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
482 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
483
[email protected]127f18ec2012-06-16 05:05:59484
Sean Kau46e29bc2017-08-28 16:31:16485# These paths contain test data and other known invalid JSON files.
486_KNOWN_INVALID_JSON_FILE_PATTERNS = [
487 r'test[\\\/]data[\\\/]',
488 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
489 r'^third_party[\\\/]protobuf[\\\/]',
490]
491
492
[email protected]b00342e7f2013-03-26 16:21:54493_VALID_OS_MACROS = (
494 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08495 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54496 'OS_ANDROID',
497 'OS_BSD',
498 'OS_CAT', # For testing.
499 'OS_CHROMEOS',
500 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37501 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54502 'OS_IOS',
503 'OS_LINUX',
504 'OS_MACOSX',
505 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21506 'OS_NACL_NONSFI',
507 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12508 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54509 'OS_OPENBSD',
510 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37511 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54512 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54513 'OS_WIN',
514)
515
516
agrievef32bcc72016-04-04 14:57:40517_ANDROID_SPECIFIC_PYDEPS_FILES = [
518 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04519 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58520 'build/secondary/third_party/android_platform/'
521 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19522 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40523]
524
wnwenbdc444e2016-05-25 13:44:15525
agrievef32bcc72016-04-04 14:57:40526_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40527]
528
wnwenbdc444e2016-05-25 13:44:15529
agrievef32bcc72016-04-04 14:57:40530_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
531
532
[email protected]55459852011-08-10 15:17:19533def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
534 """Attempts to prevent use of functions intended only for testing in
535 non-testing code. For now this is just a best-effort implementation
536 that ignores header files and may have some false positives. A
537 better implementation would probably need a proper C++ parser.
538 """
539 # We only scan .cc files and the like, as the declaration of
540 # for-testing functions in header files are hard to distinguish from
541 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44542 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19543
jochenc0d4808c2015-07-27 09:25:42544 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19545 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09546 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19547 exclusion_pattern = input_api.re.compile(
548 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
549 base_function_pattern, base_function_pattern))
550
551 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44552 black_list = (_EXCLUDED_PATHS +
553 _TEST_CODE_EXCLUDED_PATHS +
554 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19555 return input_api.FilterSourceFile(
556 affected_file,
557 white_list=(file_inclusion_pattern, ),
558 black_list=black_list)
559
560 problems = []
561 for f in input_api.AffectedSourceFiles(FilterFile):
562 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24563 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03564 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46565 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03566 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19567 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03568 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19569
570 if problems:
[email protected]f7051d52013-04-02 18:31:42571 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03572 else:
573 return []
[email protected]55459852011-08-10 15:17:19574
575
[email protected]10689ca2011-09-02 02:31:54576def _CheckNoIOStreamInHeaders(input_api, output_api):
577 """Checks to make sure no .h files include <iostream>."""
578 files = []
579 pattern = input_api.re.compile(r'^#include\s*<iostream>',
580 input_api.re.MULTILINE)
581 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
582 if not f.LocalPath().endswith('.h'):
583 continue
584 contents = input_api.ReadFile(f)
585 if pattern.search(contents):
586 files.append(f)
587
588 if len(files):
yolandyandaabc6d2016-04-18 18:29:39589 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06590 'Do not #include <iostream> in header files, since it inserts static '
591 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54592 '#include <ostream>. See http://crbug.com/94794',
593 files) ]
594 return []
595
596
[email protected]72df4e782012-06-21 16:28:18597def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52598 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18599 problems = []
600 for f in input_api.AffectedFiles():
601 if (not f.LocalPath().endswith(('.cc', '.mm'))):
602 continue
603
604 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04605 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18606 problems.append(' %s:%d' % (f.LocalPath(), line_num))
607
608 if not problems:
609 return []
610 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
611 '\n'.join(problems))]
612
613
danakj61c1aa22015-10-26 19:55:52614def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57615 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52616 errors = []
617 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
618 input_api.re.MULTILINE)
619 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
620 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
621 continue
622 for lnum, line in f.ChangedContents():
623 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17624 errors.append(output_api.PresubmitError(
625 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57626 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17627 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52628 return errors
629
630
mcasasb7440c282015-02-04 14:52:19631def _FindHistogramNameInLine(histogram_name, line):
632 """Tries to find a histogram name or prefix in a line."""
633 if not "affected-histogram" in line:
634 return histogram_name in line
635 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
636 # the histogram_name.
637 if not '"' in line:
638 return False
639 histogram_prefix = line.split('\"')[1]
640 return histogram_prefix in histogram_name
641
642
643def _CheckUmaHistogramChanges(input_api, output_api):
644 """Check that UMA histogram names in touched lines can still be found in other
645 lines of the patch or in histograms.xml. Note that this check would not catch
646 the reverse: changes in histograms.xml not matched in the code itself."""
647 touched_histograms = []
648 histograms_xml_modifications = []
649 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
650 for f in input_api.AffectedFiles():
651 # If histograms.xml itself is modified, keep the modified lines for later.
652 if f.LocalPath().endswith(('histograms.xml')):
653 histograms_xml_modifications = f.ChangedContents()
654 continue
655 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
656 continue
657 for line_num, line in f.ChangedContents():
658 found = pattern.search(line)
659 if found:
660 touched_histograms.append([found.group(1), f, line_num])
661
662 # Search for the touched histogram names in the local modifications to
663 # histograms.xml, and, if not found, on the base histograms.xml file.
664 unmatched_histograms = []
665 for histogram_info in touched_histograms:
666 histogram_name_found = False
667 for line_num, line in histograms_xml_modifications:
668 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
669 if histogram_name_found:
670 break
671 if not histogram_name_found:
672 unmatched_histograms.append(histogram_info)
673
eromanb90c82e7e32015-04-01 15:13:49674 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19675 problems = []
676 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49677 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19678 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45679 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19680 histogram_name_found = False
681 for line in histograms_xml:
682 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
683 if histogram_name_found:
684 break
685 if not histogram_name_found:
686 problems.append(' [%s:%d] %s' %
687 (f.LocalPath(), line_num, histogram_name))
688
689 if not problems:
690 return []
691 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
692 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49693 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19694
wnwenbdc444e2016-05-25 13:44:15695
yolandyandaabc6d2016-04-18 18:29:39696def _CheckFlakyTestUsage(input_api, output_api):
697 """Check that FlakyTest annotation is our own instead of the android one"""
698 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
699 files = []
700 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
701 if f.LocalPath().endswith('Test.java'):
702 if pattern.search(input_api.ReadFile(f)):
703 files.append(f)
704 if len(files):
705 return [output_api.PresubmitError(
706 'Use org.chromium.base.test.util.FlakyTest instead of '
707 'android.test.FlakyTest',
708 files)]
709 return []
mcasasb7440c282015-02-04 14:52:19710
wnwenbdc444e2016-05-25 13:44:15711
[email protected]8ea5d4b2011-09-13 21:49:22712def _CheckNoNewWStrings(input_api, output_api):
713 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27714 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22715 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20716 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57717 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34718 '/win/' in f.LocalPath() or
719 'chrome_elf' in f.LocalPath() or
720 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20721 continue
[email protected]8ea5d4b2011-09-13 21:49:22722
[email protected]a11dbe9b2012-08-07 01:32:58723 allowWString = False
[email protected]b5c24292011-11-28 14:38:20724 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58725 if 'presubmit: allow wstring' in line:
726 allowWString = True
727 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27728 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58729 allowWString = False
730 else:
731 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22732
[email protected]55463aa62011-10-12 00:48:27733 if not problems:
734 return []
735 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58736 ' If you are calling a cross-platform API that accepts a wstring, '
737 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27738 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22739
740
[email protected]2a8ac9c2011-10-19 17:20:44741def _CheckNoDEPSGIT(input_api, output_api):
742 """Make sure .DEPS.git is never modified manually."""
743 if any(f.LocalPath().endswith('.DEPS.git') for f in
744 input_api.AffectedFiles()):
745 return [output_api.PresubmitError(
746 'Never commit changes to .DEPS.git. This file is maintained by an\n'
747 'automated system based on what\'s in DEPS and your changes will be\n'
748 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34749 '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:44750 'for more information')]
751 return []
752
753
tandriief664692014-09-23 14:51:47754def _CheckValidHostsInDEPS(input_api, output_api):
755 """Checks that DEPS file deps are from allowed_hosts."""
756 # Run only if DEPS file has been modified to annoy fewer bystanders.
757 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
758 return []
759 # Outsource work to gclient verify
760 try:
761 input_api.subprocess.check_output(['gclient', 'verify'])
762 return []
763 except input_api.subprocess.CalledProcessError, error:
764 return [output_api.PresubmitError(
765 'DEPS file must have only git dependencies.',
766 long_text=error.output)]
767
768
[email protected]127f18ec2012-06-16 05:05:59769def _CheckNoBannedFunctions(input_api, output_api):
770 """Make sure that banned functions are not used."""
771 warnings = []
772 errors = []
773
wnwenbdc444e2016-05-25 13:44:15774 def IsBlacklisted(affected_file, blacklist):
775 local_path = affected_file.LocalPath()
776 for item in blacklist:
777 if input_api.re.match(item, local_path):
778 return True
779 return False
780
781 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
782 matched = False
783 if func_name[0:1] == '/':
784 regex = func_name[1:]
785 if input_api.re.search(regex, line):
786 matched = True
787 elif func_name in line:
dchenge07de812016-06-20 19:27:17788 matched = True
wnwenbdc444e2016-05-25 13:44:15789 if matched:
dchenge07de812016-06-20 19:27:17790 problems = warnings
wnwenbdc444e2016-05-25 13:44:15791 if error:
dchenge07de812016-06-20 19:27:17792 problems = errors
wnwenbdc444e2016-05-25 13:44:15793 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
794 for message_line in message:
795 problems.append(' %s' % message_line)
796
Eric Stevensona9a980972017-09-23 00:04:41797 file_filter = lambda f: f.LocalPath().endswith(('.java'))
798 for f in input_api.AffectedFiles(file_filter=file_filter):
799 for line_num, line in f.ChangedContents():
800 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
801 CheckForMatch(f, line_num, line, func_name, message, error)
802
[email protected]127f18ec2012-06-16 05:05:59803 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
804 for f in input_api.AffectedFiles(file_filter=file_filter):
805 for line_num, line in f.ChangedContents():
806 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15807 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59808
809 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
810 for f in input_api.AffectedFiles(file_filter=file_filter):
811 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49812 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49813 if IsBlacklisted(f, excluded_paths):
814 continue
wnwenbdc444e2016-05-25 13:44:15815 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59816
817 result = []
818 if (warnings):
819 result.append(output_api.PresubmitPromptWarning(
820 'Banned functions were used.\n' + '\n'.join(warnings)))
821 if (errors):
822 result.append(output_api.PresubmitError(
823 'Banned functions were used.\n' + '\n'.join(errors)))
824 return result
825
826
[email protected]6c063c62012-07-11 19:11:06827def _CheckNoPragmaOnce(input_api, output_api):
828 """Make sure that banned functions are not used."""
829 files = []
830 pattern = input_api.re.compile(r'^#pragma\s+once',
831 input_api.re.MULTILINE)
832 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
833 if not f.LocalPath().endswith('.h'):
834 continue
835 contents = input_api.ReadFile(f)
836 if pattern.search(contents):
837 files.append(f)
838
839 if files:
840 return [output_api.PresubmitError(
841 'Do not use #pragma once in header files.\n'
842 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
843 files)]
844 return []
845
[email protected]127f18ec2012-06-16 05:05:59846
[email protected]e7479052012-09-19 00:26:12847def _CheckNoTrinaryTrueFalse(input_api, output_api):
848 """Checks to make sure we don't introduce use of foo ? true : false."""
849 problems = []
850 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
851 for f in input_api.AffectedFiles():
852 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
853 continue
854
855 for line_num, line in f.ChangedContents():
856 if pattern.match(line):
857 problems.append(' %s:%d' % (f.LocalPath(), line_num))
858
859 if not problems:
860 return []
861 return [output_api.PresubmitPromptWarning(
862 'Please consider avoiding the "? true : false" pattern if possible.\n' +
863 '\n'.join(problems))]
864
865
[email protected]55f9f382012-07-31 11:02:18866def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28867 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18868 change. Breaking - rules is an error, breaking ! rules is a
869 warning.
870 """
mohan.reddyf21db962014-10-16 12:26:47871 import sys
[email protected]55f9f382012-07-31 11:02:18872 # We need to wait until we have an input_api object and use this
873 # roundabout construct to import checkdeps because this file is
874 # eval-ed and thus doesn't have __file__.
875 original_sys_path = sys.path
876 try:
877 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47878 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18879 import checkdeps
880 from cpp_checker import CppChecker
rhalavati08acd232017-04-03 07:23:28881 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18882 from rules import Rule
883 finally:
884 # Restore sys.path to what it was before.
885 sys.path = original_sys_path
886
887 added_includes = []
rhalavati08acd232017-04-03 07:23:28888 added_imports = []
[email protected]55f9f382012-07-31 11:02:18889 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28890 if CppChecker.IsCppFile(f.LocalPath()):
891 changed_lines = [line for line_num, line in f.ChangedContents()]
892 added_includes.append([f.LocalPath(), changed_lines])
893 elif ProtoChecker.IsProtoFile(f.LocalPath()):
894 changed_lines = [line for line_num, line in f.ChangedContents()]
895 added_imports.append([f.LocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18896
[email protected]26385172013-05-09 23:11:35897 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18898
899 error_descriptions = []
900 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28901 error_subjects = set()
902 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18903 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
904 added_includes):
905 description_with_path = '%s\n %s' % (path, rule_description)
906 if rule_type == Rule.DISALLOW:
907 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28908 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18909 else:
910 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28911 warning_subjects.add("#includes")
912
913 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
914 added_imports):
915 description_with_path = '%s\n %s' % (path, rule_description)
916 if rule_type == Rule.DISALLOW:
917 error_descriptions.append(description_with_path)
918 error_subjects.add("imports")
919 else:
920 warning_descriptions.append(description_with_path)
921 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18922
923 results = []
924 if error_descriptions:
925 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28926 'You added one or more %s that violate checkdeps rules.'
927 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18928 error_descriptions))
929 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42930 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28931 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18932 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28933 '%s? See relevant DEPS file(s) for details and contacts.' %
934 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18935 warning_descriptions))
936 return results
937
938
[email protected]fbcafe5a2012-08-08 15:31:22939def _CheckFilePermissions(input_api, output_api):
940 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15941 if input_api.platform == 'win32':
942 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29943 checkperms_tool = input_api.os_path.join(
944 input_api.PresubmitLocalPath(),
945 'tools', 'checkperms', 'checkperms.py')
946 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47947 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22948 for f in input_api.AffectedFiles():
949 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11950 try:
951 input_api.subprocess.check_output(args)
952 return []
953 except input_api.subprocess.CalledProcessError as error:
954 return [output_api.PresubmitError(
955 'checkperms.py failed:',
956 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22957
958
robertocn832f5992017-01-04 19:01:30959def _CheckTeamTags(input_api, output_api):
960 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
961 checkteamtags_tool = input_api.os_path.join(
962 input_api.PresubmitLocalPath(),
963 'tools', 'checkteamtags', 'checkteamtags.py')
964 args = [input_api.python_executable, checkteamtags_tool,
965 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22966 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30967 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
968 'OWNERS']
969 try:
970 if files:
971 input_api.subprocess.check_output(args + files)
972 return []
973 except input_api.subprocess.CalledProcessError as error:
974 return [output_api.PresubmitError(
975 'checkteamtags.py failed:',
976 long_text=error.output)]
977
978
[email protected]c8278b32012-10-30 20:35:49979def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
980 """Makes sure we don't include ui/aura/window_property.h
981 in header files.
982 """
983 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
984 errors = []
985 for f in input_api.AffectedFiles():
986 if not f.LocalPath().endswith('.h'):
987 continue
988 for line_num, line in f.ChangedContents():
989 if pattern.match(line):
990 errors.append(' %s:%d' % (f.LocalPath(), line_num))
991
992 results = []
993 if errors:
994 results.append(output_api.PresubmitError(
995 'Header files should not include ui/aura/window_property.h', errors))
996 return results
997
998
[email protected]70ca77752012-11-20 03:45:03999def _CheckForVersionControlConflictsInFile(input_api, f):
1000 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1001 errors = []
1002 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:231003 if f.LocalPath().endswith('.md'):
1004 # First-level headers in markdown look a lot like version control
1005 # conflict markers. http://daringfireball.net/projects/markdown/basics
1006 continue
[email protected]70ca77752012-11-20 03:45:031007 if pattern.match(line):
1008 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1009 return errors
1010
1011
1012def _CheckForVersionControlConflicts(input_api, output_api):
1013 """Usually this is not intentional and will cause a compile failure."""
1014 errors = []
1015 for f in input_api.AffectedFiles():
1016 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1017
1018 results = []
1019 if errors:
1020 results.append(output_api.PresubmitError(
1021 'Version control conflict markers found, please resolve.', errors))
1022 return results
1023
estadee17314a02017-01-12 16:22:161024def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1025 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1026 errors = []
1027 for f in input_api.AffectedFiles():
1028 for line_num, line in f.ChangedContents():
1029 if pattern.search(line):
1030 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1031
1032 results = []
1033 if errors:
1034 results.append(output_api.PresubmitPromptWarning(
1035 'Found Google support URL addressed by answer number. Please replace with '
1036 'a p= identifier instead. See crbug.com/679462\n', errors))
1037 return results
1038
[email protected]70ca77752012-11-20 03:45:031039
[email protected]06e6d0ff2012-12-11 01:36:441040def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1041 def FilterFile(affected_file):
1042 """Filter function for use with input_api.AffectedSourceFiles,
1043 below. This filters out everything except non-test files from
1044 top-level directories that generally speaking should not hard-code
1045 service URLs (e.g. src/android_webview/, src/content/ and others).
1046 """
1047 return input_api.FilterSourceFile(
1048 affected_file,
[email protected]78bb39d62012-12-11 15:11:561049 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441050 black_list=(_EXCLUDED_PATHS +
1051 _TEST_CODE_EXCLUDED_PATHS +
1052 input_api.DEFAULT_BLACK_LIST))
1053
reillyi38965732015-11-16 18:27:331054 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1055 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461056 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1057 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441058 problems = [] # items are (filename, line_number, line)
1059 for f in input_api.AffectedSourceFiles(FilterFile):
1060 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461061 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441062 problems.append((f.LocalPath(), line_num, line))
1063
1064 if problems:
[email protected]f7051d52013-04-02 18:31:421065 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441066 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581067 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441068 [' %s:%d: %s' % (
1069 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031070 else:
1071 return []
[email protected]06e6d0ff2012-12-11 01:36:441072
1073
[email protected]d2530012013-01-25 16:39:271074def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1075 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311076 The native_client_sdk directory is excluded because it has auto-generated PNG
1077 files for documentation.
[email protected]d2530012013-01-25 16:39:271078 """
[email protected]d2530012013-01-25 16:39:271079 errors = []
binji0dcdf342014-12-12 18:32:311080 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1081 black_list = (r'^native_client_sdk[\\\/]',)
1082 file_filter = lambda f: input_api.FilterSourceFile(
1083 f, white_list=white_list, black_list=black_list)
1084 for f in input_api.AffectedFiles(include_deletes=False,
1085 file_filter=file_filter):
1086 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271087
1088 results = []
1089 if errors:
1090 results.append(output_api.PresubmitError(
1091 'The name of PNG files should not have abbreviations. \n'
1092 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1093 'Contact [email protected] if you have questions.', errors))
1094 return results
1095
1096
Daniel Cheng4dcdb6b2017-04-13 08:30:171097def _ExtractAddRulesFromParsedDeps(parsed_deps):
1098 """Extract the rules that add dependencies from a parsed DEPS file.
1099
1100 Args:
1101 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1102 add_rules = set()
1103 add_rules.update([
1104 rule[1:] for rule in parsed_deps.get('include_rules', [])
1105 if rule.startswith('+') or rule.startswith('!')
1106 ])
1107 for specific_file, rules in parsed_deps.get('specific_include_rules',
1108 {}).iteritems():
1109 add_rules.update([
1110 rule[1:] for rule in rules
1111 if rule.startswith('+') or rule.startswith('!')
1112 ])
1113 return add_rules
1114
1115
1116def _ParseDeps(contents):
1117 """Simple helper for parsing DEPS files."""
1118 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171119 class _VarImpl:
1120
1121 def __init__(self, local_scope):
1122 self._local_scope = local_scope
1123
1124 def Lookup(self, var_name):
1125 """Implements the Var syntax."""
1126 try:
1127 return self._local_scope['vars'][var_name]
1128 except KeyError:
1129 raise Exception('Var is not defined: %s' % var_name)
1130
1131 local_scope = {}
1132 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171133 'Var': _VarImpl(local_scope).Lookup,
1134 }
1135 exec contents in global_scope, local_scope
1136 return local_scope
1137
1138
1139def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081140 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411141 a set of DEPS entries that we should look up.
1142
1143 For a directory (rather than a specific filename) we fake a path to
1144 a specific filename by adding /DEPS. This is chosen as a file that
1145 will seldom or never be subject to per-file include_rules.
1146 """
[email protected]2b438d62013-11-14 17:54:141147 # We ignore deps entries on auto-generated directories.
1148 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081149
Daniel Cheng4dcdb6b2017-04-13 08:30:171150 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1151 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1152
1153 added_deps = new_deps.difference(old_deps)
1154
[email protected]2b438d62013-11-14 17:54:141155 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171156 for added_dep in added_deps:
1157 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1158 continue
1159 # Assume that a rule that ends in .h is a rule for a specific file.
1160 if added_dep.endswith('.h'):
1161 results.add(added_dep)
1162 else:
1163 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081164 return results
1165
1166
[email protected]e871964c2013-05-13 14:14:551167def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1168 """When a dependency prefixed with + is added to a DEPS file, we
1169 want to make sure that the change is reviewed by an OWNER of the
1170 target file or directory, to avoid layering violations from being
1171 introduced. This check verifies that this happens.
1172 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171173 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241174
1175 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191176 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241177 for f in input_api.AffectedFiles(include_deletes=False,
1178 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551179 filename = input_api.os_path.basename(f.LocalPath())
1180 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171181 virtual_depended_on_files.update(_CalculateAddedDeps(
1182 input_api.os_path,
1183 '\n'.join(f.OldContents()),
1184 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551185
[email protected]e871964c2013-05-13 14:14:551186 if not virtual_depended_on_files:
1187 return []
1188
1189 if input_api.is_committing:
1190 if input_api.tbr:
1191 return [output_api.PresubmitNotifyResult(
1192 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271193 if input_api.dry_run:
1194 return [output_api.PresubmitNotifyResult(
1195 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551196 if not input_api.change.issue:
1197 return [output_api.PresubmitError(
1198 "DEPS approval by OWNERS check failed: this change has "
1199 "no Rietveld issue number, so we can't check it for approvals.")]
1200 output = output_api.PresubmitError
1201 else:
1202 output = output_api.PresubmitNotifyResult
1203
1204 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501205 owner_email, reviewers = (
1206 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1207 input_api,
1208 owners_db.email_regexp,
1209 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551210
1211 owner_email = owner_email or input_api.change.author_email
1212
[email protected]de4f7d22013-05-23 14:27:461213 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511214 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461215 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551216 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1217 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411218
1219 # We strip the /DEPS part that was added by
1220 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1221 # directory.
1222 def StripDeps(path):
1223 start_deps = path.rfind('/DEPS')
1224 if start_deps != -1:
1225 return path[:start_deps]
1226 else:
1227 return path
1228 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551229 for path in missing_files]
1230
1231 if unapproved_dependencies:
1232 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151233 output('You need LGTM from owners of depends-on paths in DEPS that were '
1234 'modified in this CL:\n %s' %
1235 '\n '.join(sorted(unapproved_dependencies)))]
1236 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1237 output_list.append(output(
1238 'Suggested missing target path OWNERS:\n %s' %
1239 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551240 return output_list
1241
1242 return []
1243
1244
[email protected]85218562013-11-22 07:41:401245def _CheckSpamLogging(input_api, output_api):
1246 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1247 black_list = (_EXCLUDED_PATHS +
1248 _TEST_CODE_EXCLUDED_PATHS +
1249 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501250 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191251 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481252 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461253 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121254 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1255 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581256 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591257 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161258 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031259 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151260 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1261 r"^chromecast[\\\/]",
1262 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481263 r"^components[\\\/]browser_watcher[\\\/]"
1264 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311265 r"^components[\\\/]html_viewer[\\\/]"
1266 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461267 # TODO(peter): Remove this exception. https://crbug.com/534537
1268 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1269 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251270 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1271 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241272 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111273 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151274 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111275 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521276 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501277 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361278 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311279 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131280 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001281 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441282 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451283 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021284 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351285 r"dump_file_system.cc$",
1286 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401287 source_file_filter = lambda x: input_api.FilterSourceFile(
1288 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1289
thomasanderson625d3932017-03-29 07:16:581290 log_info = set([])
1291 printf = set([])
[email protected]85218562013-11-22 07:41:401292
1293 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581294 for _, line in f.ChangedContents():
1295 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1296 log_info.add(f.LocalPath())
1297 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1298 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371299
thomasanderson625d3932017-03-29 07:16:581300 if input_api.re.search(r"\bprintf\(", line):
1301 printf.add(f.LocalPath())
1302 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1303 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401304
1305 if log_info:
1306 return [output_api.PresubmitError(
1307 'These files spam the console log with LOG(INFO):',
1308 items=log_info)]
1309 if printf:
1310 return [output_api.PresubmitError(
1311 'These files spam the console log with printf/fprintf:',
1312 items=printf)]
1313 return []
1314
1315
[email protected]49aa76a2013-12-04 06:59:161316def _CheckForAnonymousVariables(input_api, output_api):
1317 """These types are all expected to hold locks while in scope and
1318 so should never be anonymous (which causes them to be immediately
1319 destroyed)."""
1320 they_who_must_be_named = [
1321 'base::AutoLock',
1322 'base::AutoReset',
1323 'base::AutoUnlock',
1324 'SkAutoAlphaRestore',
1325 'SkAutoBitmapShaderInstall',
1326 'SkAutoBlitterChoose',
1327 'SkAutoBounderCommit',
1328 'SkAutoCallProc',
1329 'SkAutoCanvasRestore',
1330 'SkAutoCommentBlock',
1331 'SkAutoDescriptor',
1332 'SkAutoDisableDirectionCheck',
1333 'SkAutoDisableOvalCheck',
1334 'SkAutoFree',
1335 'SkAutoGlyphCache',
1336 'SkAutoHDC',
1337 'SkAutoLockColors',
1338 'SkAutoLockPixels',
1339 'SkAutoMalloc',
1340 'SkAutoMaskFreeImage',
1341 'SkAutoMutexAcquire',
1342 'SkAutoPathBoundsUpdate',
1343 'SkAutoPDFRelease',
1344 'SkAutoRasterClipValidate',
1345 'SkAutoRef',
1346 'SkAutoTime',
1347 'SkAutoTrace',
1348 'SkAutoUnref',
1349 ]
1350 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1351 # bad: base::AutoLock(lock.get());
1352 # not bad: base::AutoLock lock(lock.get());
1353 bad_pattern = input_api.re.compile(anonymous)
1354 # good: new base::AutoLock(lock.get())
1355 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1356 errors = []
1357
1358 for f in input_api.AffectedFiles():
1359 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1360 continue
1361 for linenum, line in f.ChangedContents():
1362 if bad_pattern.search(line) and not good_pattern.search(line):
1363 errors.append('%s:%d' % (f.LocalPath(), linenum))
1364
1365 if errors:
1366 return [output_api.PresubmitError(
1367 'These lines create anonymous variables that need to be named:',
1368 items=errors)]
1369 return []
1370
1371
[email protected]999261d2014-03-03 20:08:081372def _CheckUserActionUpdate(input_api, output_api):
1373 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521374 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081375 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521376 # If actions.xml is already included in the changelist, the PRESUBMIT
1377 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081378 return []
1379
[email protected]999261d2014-03-03 20:08:081380 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1381 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521382 current_actions = None
[email protected]999261d2014-03-03 20:08:081383 for f in input_api.AffectedFiles(file_filter=file_filter):
1384 for line_num, line in f.ChangedContents():
1385 match = input_api.re.search(action_re, line)
1386 if match:
[email protected]2f92dec2014-03-07 19:21:521387 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1388 # loaded only once.
1389 if not current_actions:
1390 with open('tools/metrics/actions/actions.xml') as actions_f:
1391 current_actions = actions_f.read()
1392 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081393 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521394 action = 'name="{0}"'.format(action_name)
1395 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081396 return [output_api.PresubmitPromptWarning(
1397 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521398 'tools/metrics/actions/actions.xml. Please run '
1399 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081400 % (f.LocalPath(), line_num, action_name))]
1401 return []
1402
1403
Daniel Cheng13ca61a882017-08-25 15:11:251404def _ImportJSONCommentEater(input_api):
1405 import sys
1406 sys.path = sys.path + [input_api.os_path.join(
1407 input_api.PresubmitLocalPath(),
1408 'tools', 'json_comment_eater')]
1409 import json_comment_eater
1410 return json_comment_eater
1411
1412
[email protected]99171a92014-06-03 08:44:471413def _GetJSONParseError(input_api, filename, eat_comments=True):
1414 try:
1415 contents = input_api.ReadFile(filename)
1416 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251417 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131418 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471419
1420 input_api.json.loads(contents)
1421 except ValueError as e:
1422 return e
1423 return None
1424
1425
1426def _GetIDLParseError(input_api, filename):
1427 try:
1428 contents = input_api.ReadFile(filename)
1429 idl_schema = input_api.os_path.join(
1430 input_api.PresubmitLocalPath(),
1431 'tools', 'json_schema_compiler', 'idl_schema.py')
1432 process = input_api.subprocess.Popen(
1433 [input_api.python_executable, idl_schema],
1434 stdin=input_api.subprocess.PIPE,
1435 stdout=input_api.subprocess.PIPE,
1436 stderr=input_api.subprocess.PIPE,
1437 universal_newlines=True)
1438 (_, error) = process.communicate(input=contents)
1439 return error or None
1440 except ValueError as e:
1441 return e
1442
1443
1444def _CheckParseErrors(input_api, output_api):
1445 """Check that IDL and JSON files do not contain syntax errors."""
1446 actions = {
1447 '.idl': _GetIDLParseError,
1448 '.json': _GetJSONParseError,
1449 }
[email protected]99171a92014-06-03 08:44:471450 # Most JSON files are preprocessed and support comments, but these do not.
1451 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491452 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471453 ]
1454 # Only run IDL checker on files in these directories.
1455 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491456 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1457 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471458 ]
1459
1460 def get_action(affected_file):
1461 filename = affected_file.LocalPath()
1462 return actions.get(input_api.os_path.splitext(filename)[1])
1463
[email protected]99171a92014-06-03 08:44:471464 def FilterFile(affected_file):
1465 action = get_action(affected_file)
1466 if not action:
1467 return False
1468 path = affected_file.LocalPath()
1469
Sean Kau46e29bc2017-08-28 16:31:161470 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471471 return False
1472
1473 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161474 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471475 return False
1476 return True
1477
1478 results = []
1479 for affected_file in input_api.AffectedFiles(
1480 file_filter=FilterFile, include_deletes=False):
1481 action = get_action(affected_file)
1482 kwargs = {}
1483 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161484 _MatchesFile(input_api, json_no_comments_patterns,
1485 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471486 kwargs['eat_comments'] = False
1487 parse_error = action(input_api,
1488 affected_file.AbsoluteLocalPath(),
1489 **kwargs)
1490 if parse_error:
1491 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1492 (affected_file.LocalPath(), parse_error)))
1493 return results
1494
1495
[email protected]760deea2013-12-10 19:33:491496def _CheckJavaStyle(input_api, output_api):
1497 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471498 import sys
[email protected]760deea2013-12-10 19:33:491499 original_sys_path = sys.path
1500 try:
1501 sys.path = sys.path + [input_api.os_path.join(
1502 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1503 import checkstyle
1504 finally:
1505 # Restore sys.path to what it was before.
1506 sys.path = original_sys_path
1507
1508 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091509 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511510 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491511
1512
Sean Kau46e29bc2017-08-28 16:31:161513def _MatchesFile(input_api, patterns, path):
1514 for pattern in patterns:
1515 if input_api.re.search(pattern, path):
1516 return True
1517 return False
1518
1519
dchenge07de812016-06-20 19:27:171520def _CheckIpcOwners(input_api, output_api):
1521 """Checks that affected files involving IPC have an IPC OWNERS rule.
1522
1523 Whether or not a file affects IPC is determined by a simple whitelist of
1524 filename patterns."""
1525 file_patterns = [
palmerb19a0932017-01-24 04:00:311526 # Legacy IPC:
dchenge07de812016-06-20 19:27:171527 '*_messages.cc',
1528 '*_messages*.h',
1529 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311530 # Mojo IPC:
dchenge07de812016-06-20 19:27:171531 '*.mojom',
1532 '*_struct_traits*.*',
1533 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311534 '*.typemap',
1535 # Android native IPC:
1536 '*.aidl',
1537 # Blink uses a different file naming convention:
1538 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171539 '*StructTraits*.*',
1540 '*TypeConverter*.*',
1541 ]
1542
scottmg7a6ed5ba2016-11-04 18:22:041543 # These third_party directories do not contain IPCs, but contain files
1544 # matching the above patterns, which trigger false positives.
1545 exclude_paths = [
1546 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291547 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041548 ]
1549
dchenge07de812016-06-20 19:27:171550 # Dictionary mapping an OWNERS file path to Patterns.
1551 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1552 # rules ) to a PatternEntry.
1553 # PatternEntry is a dictionary with two keys:
1554 # - 'files': the files that are matched by this pattern
1555 # - 'rules': the per-file rules needed for this pattern
1556 # For example, if we expect OWNERS file to contain rules for *.mojom and
1557 # *_struct_traits*.*, Patterns might look like this:
1558 # {
1559 # '*.mojom': {
1560 # 'files': ...,
1561 # 'rules': [
1562 # 'per-file *.mojom=set noparent',
1563 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1564 # ],
1565 # },
1566 # '*_struct_traits*.*': {
1567 # 'files': ...,
1568 # 'rules': [
1569 # 'per-file *_struct_traits*.*=set noparent',
1570 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1571 # ],
1572 # },
1573 # }
1574 to_check = {}
1575
Daniel Cheng13ca61a882017-08-25 15:11:251576 def AddPatternToCheck(input_file, pattern):
1577 owners_file = input_api.os_path.join(
1578 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1579 if owners_file not in to_check:
1580 to_check[owners_file] = {}
1581 if pattern not in to_check[owners_file]:
1582 to_check[owners_file][pattern] = {
1583 'files': [],
1584 'rules': [
1585 'per-file %s=set noparent' % pattern,
1586 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1587 ]
1588 }
1589 to_check[owners_file][pattern]['files'].append(f)
1590
dchenge07de812016-06-20 19:27:171591 # Iterate through the affected files to see what we actually need to check
1592 # for. We should only nag patch authors about per-file rules if a file in that
1593 # directory would match that pattern. If a directory only contains *.mojom
1594 # files and no *_messages*.h files, we should only nag about rules for
1595 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251596 for f in input_api.AffectedFiles(include_deletes=False):
1597 # Manifest files don't have a strong naming convention. Instead, scan
1598 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161599 if (f.LocalPath().endswith('.json') and
1600 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1601 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251602 json_comment_eater = _ImportJSONCommentEater(input_api)
1603 mostly_json_lines = '\n'.join(f.NewContents())
1604 # Comments aren't allowed in strict JSON, so filter them out.
1605 json_lines = json_comment_eater.Nom(mostly_json_lines)
1606 json_content = input_api.json.loads(json_lines)
1607 if 'interface_provider_specs' in json_content:
1608 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171609 for pattern in file_patterns:
1610 if input_api.fnmatch.fnmatch(
1611 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041612 skip = False
1613 for exclude in exclude_paths:
1614 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1615 skip = True
1616 break
1617 if skip:
1618 continue
Daniel Cheng13ca61a882017-08-25 15:11:251619 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171620 break
1621
1622 # Now go through the OWNERS files we collected, filtering out rules that are
1623 # already present in that OWNERS file.
1624 for owners_file, patterns in to_check.iteritems():
1625 try:
1626 with file(owners_file) as f:
1627 lines = set(f.read().splitlines())
1628 for entry in patterns.itervalues():
1629 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1630 ]
1631 except IOError:
1632 # No OWNERS file, so all the rules are definitely missing.
1633 continue
1634
1635 # All the remaining lines weren't found in OWNERS files, so emit an error.
1636 errors = []
1637 for owners_file, patterns in to_check.iteritems():
1638 missing_lines = []
1639 files = []
1640 for pattern, entry in patterns.iteritems():
1641 missing_lines.extend(entry['rules'])
1642 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1643 if missing_lines:
1644 errors.append(
Daniel Cheng52111692017-06-14 08:00:591645 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171646 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1647
1648 results = []
1649 if errors:
vabrf5ce3bf92016-07-11 14:52:411650 if input_api.is_committing:
1651 output = output_api.PresubmitError
1652 else:
1653 output = output_api.PresubmitPromptWarning
1654 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591655 'Found OWNERS files that need to be updated for IPC security ' +
1656 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171657 long_text='\n\n'.join(errors)))
1658
1659 return results
1660
1661
jbriance9e12f162016-11-25 07:57:501662def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311663 """Checks that added or removed lines in non third party affected
1664 header files do not lead to new useless class or struct forward
1665 declaration.
jbriance9e12f162016-11-25 07:57:501666 """
1667 results = []
1668 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1669 input_api.re.MULTILINE)
1670 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1671 input_api.re.MULTILINE)
1672 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311673 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191674 not f.LocalPath().startswith('third_party/blink') and
1675 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311676 not f.LocalPath().startswith('third_party/WebKit') and
1677 not f.LocalPath().startswith('third_party\\WebKit')):
1678 continue
1679
jbriance9e12f162016-11-25 07:57:501680 if not f.LocalPath().endswith('.h'):
1681 continue
1682
1683 contents = input_api.ReadFile(f)
1684 fwd_decls = input_api.re.findall(class_pattern, contents)
1685 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1686
1687 useless_fwd_decls = []
1688 for decl in fwd_decls:
1689 count = sum(1 for _ in input_api.re.finditer(
1690 r'\b%s\b' % input_api.re.escape(decl), contents))
1691 if count == 1:
1692 useless_fwd_decls.append(decl)
1693
1694 if not useless_fwd_decls:
1695 continue
1696
1697 for line in f.GenerateScmDiff().splitlines():
1698 if (line.startswith('-') and not line.startswith('--') or
1699 line.startswith('+') and not line.startswith('++')):
1700 for decl in useless_fwd_decls:
1701 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1702 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241703 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501704 (f.LocalPath(), decl)))
1705 useless_fwd_decls.remove(decl)
1706
1707 return results
1708
1709
dskiba88634f4e2015-08-14 23:03:291710def _CheckAndroidToastUsage(input_api, output_api):
1711 """Checks that code uses org.chromium.ui.widget.Toast instead of
1712 android.widget.Toast (Chromium Toast doesn't force hardware
1713 acceleration on low-end devices, saving memory).
1714 """
1715 toast_import_pattern = input_api.re.compile(
1716 r'^import android\.widget\.Toast;$')
1717
1718 errors = []
1719
1720 sources = lambda affected_file: input_api.FilterSourceFile(
1721 affected_file,
1722 black_list=(_EXCLUDED_PATHS +
1723 _TEST_CODE_EXCLUDED_PATHS +
1724 input_api.DEFAULT_BLACK_LIST +
1725 (r'^chromecast[\\\/].*',
1726 r'^remoting[\\\/].*')),
1727 white_list=(r'.*\.java$',))
1728
1729 for f in input_api.AffectedSourceFiles(sources):
1730 for line_num, line in f.ChangedContents():
1731 if toast_import_pattern.search(line):
1732 errors.append("%s:%d" % (f.LocalPath(), line_num))
1733
1734 results = []
1735
1736 if errors:
1737 results.append(output_api.PresubmitError(
1738 'android.widget.Toast usage is detected. Android toasts use hardware'
1739 ' acceleration, and can be\ncostly on low-end devices. Please use'
1740 ' org.chromium.ui.widget.Toast instead.\n'
1741 'Contact [email protected] if you have any questions.',
1742 errors))
1743
1744 return results
1745
1746
dgnaa68d5e2015-06-10 10:08:221747def _CheckAndroidCrLogUsage(input_api, output_api):
1748 """Checks that new logs using org.chromium.base.Log:
1749 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511750 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221751 """
pkotwicza1dd0b002016-05-16 14:41:041752
torne89540622017-03-24 19:41:301753 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041754 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301755 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041756 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301757 # WebView license viewer code cannot depend on //base; used in stub APK.
1758 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1759 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041760 ]
1761
dgnaa68d5e2015-06-10 10:08:221762 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121763 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1764 class_in_base_pattern = input_api.re.compile(
1765 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1766 has_some_log_import_pattern = input_api.re.compile(
1767 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221768 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121769 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221770 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511771 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221772 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221773
Vincent Scheib16d7b272015-09-15 18:09:071774 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221775 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041776 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1777 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121778
dgnaa68d5e2015-06-10 10:08:221779 tag_decl_errors = []
1780 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121781 tag_errors = []
dgn38736db2015-09-18 19:20:511782 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121783 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221784
1785 for f in input_api.AffectedSourceFiles(sources):
1786 file_content = input_api.ReadFile(f)
1787 has_modified_logs = False
1788
1789 # Per line checks
dgn87d9fb62015-06-12 09:15:121790 if (cr_log_import_pattern.search(file_content) or
1791 (class_in_base_pattern.search(file_content) and
1792 not has_some_log_import_pattern.search(file_content))):
1793 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221794 for line_num, line in f.ChangedContents():
1795
1796 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121797 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221798 if match:
1799 has_modified_logs = True
1800
1801 # Make sure it uses "TAG"
1802 if not match.group('tag') == 'TAG':
1803 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121804 else:
1805 # Report non cr Log function calls in changed lines
1806 for line_num, line in f.ChangedContents():
1807 if log_call_pattern.search(line):
1808 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221809
1810 # Per file checks
1811 if has_modified_logs:
1812 # Make sure the tag is using the "cr" prefix and is not too long
1813 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511814 tag_name = match.group('name') if match else None
1815 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221816 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511817 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221818 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511819 elif '.' in tag_name:
1820 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221821
1822 results = []
1823 if tag_decl_errors:
1824 results.append(output_api.PresubmitPromptWarning(
1825 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511826 '"private static final String TAG = "<package tag>".\n'
1827 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221828 tag_decl_errors))
1829
1830 if tag_length_errors:
1831 results.append(output_api.PresubmitError(
1832 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511833 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221834 tag_length_errors))
1835
1836 if tag_errors:
1837 results.append(output_api.PresubmitPromptWarning(
1838 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1839 tag_errors))
1840
dgn87d9fb62015-06-12 09:15:121841 if util_log_errors:
dgn4401aa52015-04-29 16:26:171842 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121843 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1844 util_log_errors))
1845
dgn38736db2015-09-18 19:20:511846 if tag_with_dot_errors:
1847 results.append(output_api.PresubmitPromptWarning(
1848 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1849 tag_with_dot_errors))
1850
dgn4401aa52015-04-29 16:26:171851 return results
1852
1853
Yoland Yanb92fa522017-08-28 17:37:061854def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1855 """Checks that junit.framework.* is no longer used."""
1856 deprecated_junit_framework_pattern = input_api.re.compile(
1857 r'^import junit\.framework\..*;',
1858 input_api.re.MULTILINE)
1859 sources = lambda x: input_api.FilterSourceFile(
1860 x, white_list=(r'.*\.java$',), black_list=None)
1861 errors = []
1862 for f in input_api.AffectedFiles(sources):
1863 for line_num, line in f.ChangedContents():
1864 if deprecated_junit_framework_pattern.search(line):
1865 errors.append("%s:%d" % (f.LocalPath(), line_num))
1866
1867 results = []
1868 if errors:
1869 results.append(output_api.PresubmitError(
1870 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1871 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1872 ' if you have any question.', errors))
1873 return results
1874
1875
1876def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1877 """Checks that if new Java test classes have inheritance.
1878 Either the new test class is JUnit3 test or it is a JUnit4 test class
1879 with a base class, either case is undesirable.
1880 """
1881 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1882
1883 sources = lambda x: input_api.FilterSourceFile(
1884 x, white_list=(r'.*Test\.java$',), black_list=None)
1885 errors = []
1886 for f in input_api.AffectedFiles(sources):
1887 if not f.OldContents():
1888 class_declaration_start_flag = False
1889 for line_num, line in f.ChangedContents():
1890 if class_declaration_pattern.search(line):
1891 class_declaration_start_flag = True
1892 if class_declaration_start_flag and ' extends ' in line:
1893 errors.append('%s:%d' % (f.LocalPath(), line_num))
1894 if '{' in line:
1895 class_declaration_start_flag = False
1896
1897 results = []
1898 if errors:
1899 results.append(output_api.PresubmitPromptWarning(
1900 'The newly created files include Test classes that inherits from base'
1901 ' class. Please do not use inheritance in JUnit4 tests or add new'
1902 ' JUnit3 tests. Contact [email protected] if you have any'
1903 ' questions.', errors))
1904 return results
1905
yolandyan45001472016-12-21 21:12:421906def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1907 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1908 deprecated_annotation_import_pattern = input_api.re.compile(
1909 r'^import android\.test\.suitebuilder\.annotation\..*;',
1910 input_api.re.MULTILINE)
1911 sources = lambda x: input_api.FilterSourceFile(
1912 x, white_list=(r'.*\.java$',), black_list=None)
1913 errors = []
1914 for f in input_api.AffectedFiles(sources):
1915 for line_num, line in f.ChangedContents():
1916 if deprecated_annotation_import_pattern.search(line):
1917 errors.append("%s:%d" % (f.LocalPath(), line_num))
1918
1919 results = []
1920 if errors:
1921 results.append(output_api.PresubmitError(
1922 'Annotations in android.test.suitebuilder.annotation have been'
1923 ' deprecated since API level 24. Please use android.support.test.filters'
1924 ' from //third_party/android_support_test_runner:runner_java instead.'
1925 ' Contact [email protected] if you have any questions.', errors))
1926 return results
1927
1928
agrieve7b6479d82015-10-07 14:24:221929def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1930 """Checks if MDPI assets are placed in a correct directory."""
1931 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1932 ('/res/drawable/' in f.LocalPath() or
1933 '/res/drawable-ldrtl/' in f.LocalPath()))
1934 errors = []
1935 for f in input_api.AffectedFiles(include_deletes=False,
1936 file_filter=file_filter):
1937 errors.append(' %s' % f.LocalPath())
1938
1939 results = []
1940 if errors:
1941 results.append(output_api.PresubmitError(
1942 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1943 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1944 '/res/drawable-ldrtl/.\n'
1945 'Contact [email protected] if you have questions.', errors))
1946 return results
1947
1948
Nate Fischer535972b2017-09-16 01:06:181949def _CheckAndroidWebkitImports(input_api, output_api):
1950 """Checks that code uses org.chromium.base.Callback instead of
1951 android.widget.ValueCallback except in the WebView glue layer.
1952 """
1953 valuecallback_import_pattern = input_api.re.compile(
1954 r'^import android\.webkit\.ValueCallback;$')
1955
1956 errors = []
1957
1958 sources = lambda affected_file: input_api.FilterSourceFile(
1959 affected_file,
1960 black_list=(_EXCLUDED_PATHS +
1961 _TEST_CODE_EXCLUDED_PATHS +
1962 input_api.DEFAULT_BLACK_LIST +
1963 (r'^android_webview[\\\/]glue[\\\/].*',)),
1964 white_list=(r'.*\.java$',))
1965
1966 for f in input_api.AffectedSourceFiles(sources):
1967 for line_num, line in f.ChangedContents():
1968 if valuecallback_import_pattern.search(line):
1969 errors.append("%s:%d" % (f.LocalPath(), line_num))
1970
1971 results = []
1972
1973 if errors:
1974 results.append(output_api.PresubmitError(
1975 'android.webkit.ValueCallback usage is detected outside of the glue'
1976 ' layer. To stay compatible with the support library, android.webkit.*'
1977 ' classes should only be used inside the glue layer and'
1978 ' org.chromium.base.Callback should be used instead.',
1979 errors))
1980
1981 return results
1982
1983
agrievef32bcc72016-04-04 14:57:401984class PydepsChecker(object):
1985 def __init__(self, input_api, pydeps_files):
1986 self._file_cache = {}
1987 self._input_api = input_api
1988 self._pydeps_files = pydeps_files
1989
1990 def _LoadFile(self, path):
1991 """Returns the list of paths within a .pydeps file relative to //."""
1992 if path not in self._file_cache:
1993 with open(path) as f:
1994 self._file_cache[path] = f.read()
1995 return self._file_cache[path]
1996
1997 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1998 """Returns an interable of paths within the .pydep, relativized to //."""
1999 os_path = self._input_api.os_path
2000 pydeps_dir = os_path.dirname(pydeps_path)
2001 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
2002 if not l.startswith('*'))
2003 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
2004
2005 def _CreateFilesToPydepsMap(self):
2006 """Returns a map of local_path -> list_of_pydeps."""
2007 ret = {}
2008 for pydep_local_path in self._pydeps_files:
2009 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
2010 ret.setdefault(path, []).append(pydep_local_path)
2011 return ret
2012
2013 def ComputeAffectedPydeps(self):
2014 """Returns an iterable of .pydeps files that might need regenerating."""
2015 affected_pydeps = set()
2016 file_to_pydeps_map = None
2017 for f in self._input_api.AffectedFiles(include_deletes=True):
2018 local_path = f.LocalPath()
2019 if local_path == 'DEPS':
2020 return self._pydeps_files
2021 elif local_path.endswith('.pydeps'):
2022 if local_path in self._pydeps_files:
2023 affected_pydeps.add(local_path)
2024 elif local_path.endswith('.py'):
2025 if file_to_pydeps_map is None:
2026 file_to_pydeps_map = self._CreateFilesToPydepsMap()
2027 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
2028 return affected_pydeps
2029
2030 def DetermineIfStale(self, pydeps_path):
2031 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:412032 import difflib
agrievef32bcc72016-04-04 14:57:402033 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
2034 cmd = old_pydeps_data[1][1:].strip()
2035 new_pydeps_data = self._input_api.subprocess.check_output(
2036 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:412037 old_contents = old_pydeps_data[2:]
2038 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:402039 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:412040 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:402041
2042
2043def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
2044 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:002045 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:282046 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
2047 # Mac, so skip it on other platforms.
2048 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002049 return []
agrievef32bcc72016-04-04 14:57:402050 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
2051 is_android = input_api.os_path.exists('third_party/android_tools')
2052 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2053 results = []
2054 # First, check for new / deleted .pydeps.
2055 for f in input_api.AffectedFiles(include_deletes=True):
2056 if f.LocalPath().endswith('.pydeps'):
2057 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2058 results.append(output_api.PresubmitError(
2059 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2060 'remove %s' % f.LocalPath()))
2061 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2062 results.append(output_api.PresubmitError(
2063 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2064 'include %s' % f.LocalPath()))
2065
2066 if results:
2067 return results
2068
2069 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2070
2071 for pydep_path in checker.ComputeAffectedPydeps():
2072 try:
phajdan.jr0d9878552016-11-04 10:49:412073 result = checker.DetermineIfStale(pydep_path)
2074 if result:
2075 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402076 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412077 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2078 'To regenerate, run:\n\n %s' %
2079 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402080 except input_api.subprocess.CalledProcessError as error:
2081 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2082 long_text=error.output)]
2083
2084 return results
2085
2086
glidere61efad2015-02-18 17:39:432087def _CheckSingletonInHeaders(input_api, output_api):
2088 """Checks to make sure no header files have |Singleton<|."""
2089 def FileFilter(affected_file):
2090 # It's ok for base/memory/singleton.h to have |Singleton<|.
2091 black_list = (_EXCLUDED_PATHS +
2092 input_api.DEFAULT_BLACK_LIST +
2093 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2094 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2095
sergeyu34d21222015-09-16 00:11:442096 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432097 files = []
2098 for f in input_api.AffectedSourceFiles(FileFilter):
2099 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2100 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2101 contents = input_api.ReadFile(f)
2102 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242103 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432104 pattern.search(line)):
2105 files.append(f)
2106 break
2107
2108 if files:
yolandyandaabc6d2016-04-18 18:29:392109 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442110 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432111 'Please move them to an appropriate source file so that the ' +
2112 'template gets instantiated in a single compilation unit.',
2113 files) ]
2114 return []
2115
2116
[email protected]fd20b902014-05-09 02:14:532117_DEPRECATED_CSS = [
2118 # Values
2119 ( "-webkit-box", "flex" ),
2120 ( "-webkit-inline-box", "inline-flex" ),
2121 ( "-webkit-flex", "flex" ),
2122 ( "-webkit-inline-flex", "inline-flex" ),
2123 ( "-webkit-min-content", "min-content" ),
2124 ( "-webkit-max-content", "max-content" ),
2125
2126 # Properties
2127 ( "-webkit-background-clip", "background-clip" ),
2128 ( "-webkit-background-origin", "background-origin" ),
2129 ( "-webkit-background-size", "background-size" ),
2130 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442131 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532132
2133 # Functions
2134 ( "-webkit-gradient", "gradient" ),
2135 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2136 ( "-webkit-linear-gradient", "linear-gradient" ),
2137 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2138 ( "-webkit-radial-gradient", "radial-gradient" ),
2139 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2140]
2141
dbeam1ec68ac2016-12-15 05:22:242142def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532143 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252144 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342145 documentation and iOS CSS for dom distiller
2146 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252147 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532148 results = []
dbeam070cfe62014-10-22 06:44:022149 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252150 black_list = (_EXCLUDED_PATHS +
2151 _TEST_CODE_EXCLUDED_PATHS +
2152 input_api.DEFAULT_BLACK_LIST +
2153 (r"^chrome/common/extensions/docs",
2154 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342155 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442156 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252157 r"^native_client_sdk"))
2158 file_filter = lambda f: input_api.FilterSourceFile(
2159 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532160 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2161 for line_num, line in fpath.ChangedContents():
2162 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022163 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532164 results.append(output_api.PresubmitError(
2165 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2166 (fpath.LocalPath(), line_num, deprecated_value, value)))
2167 return results
2168
mohan.reddyf21db962014-10-16 12:26:472169
dbeam070cfe62014-10-22 06:44:022170_DEPRECATED_JS = [
2171 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2172 ( "__defineGetter__", "Object.defineProperty" ),
2173 ( "__defineSetter__", "Object.defineProperty" ),
2174]
2175
dbeam1ec68ac2016-12-15 05:22:242176def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022177 """Make sure that we don't use deprecated JS in Chrome code."""
2178 results = []
2179 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2180 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2181 input_api.DEFAULT_BLACK_LIST)
2182 file_filter = lambda f: input_api.FilterSourceFile(
2183 f, white_list=file_inclusion_pattern, black_list=black_list)
2184 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2185 for lnum, line in fpath.ChangedContents():
2186 for (deprecated, replacement) in _DEPRECATED_JS:
2187 if deprecated in line:
2188 results.append(output_api.PresubmitError(
2189 "%s:%d: Use of deprecated JS %s, use %s instead" %
2190 (fpath.LocalPath(), lnum, deprecated, replacement)))
2191 return results
2192
dpapadd651231d82017-07-21 02:44:472193def _CheckForRiskyJsArrowFunction(line_number, line):
2194 if ' => ' in line:
2195 return "line %d, is using an => (arrow) function\n %s\n" % (
2196 line_number, line)
2197 return ''
2198
2199def _CheckForRiskyJsConstLet(input_api, line_number, line):
2200 if input_api.re.match('^\s*(const|let)\s', line):
2201 return "line %d, is using const/let keyword\n %s\n" % (
2202 line_number, line)
2203 return ''
dbeam070cfe62014-10-22 06:44:022204
dbeam1ec68ac2016-12-15 05:22:242205def _CheckForRiskyJsFeatures(input_api, output_api):
2206 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002207 # 'ui/webui/resources/cr_components are not allowed on ios'
2208 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572209 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002210 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472211 results = []
dbeam1ec68ac2016-12-15 05:22:242212 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472213 arrow_error_lines = []
2214 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242215 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472216 arrow_error_lines += filter(None, [
2217 _CheckForRiskyJsArrowFunction(lnum, line),
2218 ])
dbeam1ec68ac2016-12-15 05:22:242219
dpapadd651231d82017-07-21 02:44:472220 const_let_error_lines += filter(None, [
2221 _CheckForRiskyJsConstLet(input_api, lnum, line),
2222 ])
dbeam1ec68ac2016-12-15 05:22:242223
dpapadd651231d82017-07-21 02:44:472224 if arrow_error_lines:
2225 arrow_error_lines = map(
2226 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2227 results.append(
2228 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2229"""
2230Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242231%s
2232Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2233https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472234""" % f.LocalPath()
2235 ])))
dbeam1ec68ac2016-12-15 05:22:242236
dpapadd651231d82017-07-21 02:44:472237 if const_let_error_lines:
2238 const_let_error_lines = map(
2239 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2240 results.append(
2241 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2242"""
2243Use of const/let keywords detected in:
2244%s
2245Please ensure your code does not run on iOS9 because const/let is not fully
2246supported.
2247https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2248https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2249""" % f.LocalPath()
2250 ])))
2251
2252 return results
dbeam1ec68ac2016-12-15 05:22:242253
rlanday6802cf632017-05-30 17:48:362254def _CheckForRelativeIncludes(input_api, output_api):
2255 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2256 import sys
2257 original_sys_path = sys.path
2258 try:
2259 sys.path = sys.path + [input_api.os_path.join(
2260 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2261 from cpp_checker import CppChecker
2262 finally:
2263 # Restore sys.path to what it was before.
2264 sys.path = original_sys_path
2265
2266 bad_files = {}
2267 for f in input_api.AffectedFiles(include_deletes=False):
2268 if (f.LocalPath().startswith('third_party') and
2269 not f.LocalPath().startswith('third_party/WebKit') and
2270 not f.LocalPath().startswith('third_party\\WebKit')):
2271 continue
2272
2273 if not CppChecker.IsCppFile(f.LocalPath()):
2274 continue
2275
2276 relative_includes = [line for line_num, line in f.ChangedContents()
2277 if "#include" in line and "../" in line]
2278 if not relative_includes:
2279 continue
2280 bad_files[f.LocalPath()] = relative_includes
2281
2282 if not bad_files:
2283 return []
2284
2285 error_descriptions = []
2286 for file_path, bad_lines in bad_files.iteritems():
2287 error_description = file_path
2288 for line in bad_lines:
2289 error_description += '\n ' + line
2290 error_descriptions.append(error_description)
2291
2292 results = []
2293 results.append(output_api.PresubmitError(
2294 'You added one or more relative #include paths (including "../").\n'
2295 'These shouldn\'t be used because they can be used to include headers\n'
2296 'from code that\'s not correctly specified as a dependency in the\n'
2297 'relevant BUILD.gn file(s).',
2298 error_descriptions))
2299
2300 return results
2301
Takeshi Yoshinoe387aa32017-08-02 13:16:132302
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202303def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2304 if not isinstance(key, ast.Str):
2305 return 'Key at line %d must be a string literal' % key.lineno
2306 if not isinstance(value, ast.Dict):
2307 return 'Value at line %d must be a dict' % value.lineno
2308 if len(value.keys) != 1:
2309 return 'Dict at line %d must have single entry' % value.lineno
2310 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2311 return (
2312 'Entry at line %d must have a string literal \'filepath\' as key' %
2313 value.lineno)
2314 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132315
Takeshi Yoshinoe387aa32017-08-02 13:16:132316
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202317def _CheckWatchlistsEntrySyntax(key, value, ast):
2318 if not isinstance(key, ast.Str):
2319 return 'Key at line %d must be a string literal' % key.lineno
2320 if not isinstance(value, ast.List):
2321 return 'Value at line %d must be a list' % value.lineno
2322 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132323
Takeshi Yoshinoe387aa32017-08-02 13:16:132324
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202325def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2326 mismatch_template = (
2327 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2328 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132329
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202330 i = 0
2331 last_key = ''
2332 while True:
2333 if i >= len(wd_dict.keys):
2334 if i >= len(w_dict.keys):
2335 return None
2336 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2337 elif i >= len(w_dict.keys):
2338 return (
2339 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132340
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202341 wd_key = wd_dict.keys[i]
2342 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132343
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202344 result = _CheckWatchlistDefinitionsEntrySyntax(
2345 wd_key, wd_dict.values[i], ast)
2346 if result is not None:
2347 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132348
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202349 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2350 if result is not None:
2351 return 'Bad entry in WATCHLISTS dict: %s' % result
2352
2353 if wd_key.s != w_key.s:
2354 return mismatch_template % (
2355 '%s at line %d' % (wd_key.s, wd_key.lineno),
2356 '%s at line %d' % (w_key.s, w_key.lineno))
2357
2358 if wd_key.s < last_key:
2359 return (
2360 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2361 (wd_key.lineno, w_key.lineno))
2362 last_key = wd_key.s
2363
2364 i = i + 1
2365
2366
2367def _CheckWATCHLISTSSyntax(expression, ast):
2368 if not isinstance(expression, ast.Expression):
2369 return 'WATCHLISTS file must contain a valid expression'
2370 dictionary = expression.body
2371 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2372 return 'WATCHLISTS file must have single dict with exactly two entries'
2373
2374 first_key = dictionary.keys[0]
2375 first_value = dictionary.values[0]
2376 second_key = dictionary.keys[1]
2377 second_value = dictionary.values[1]
2378
2379 if (not isinstance(first_key, ast.Str) or
2380 first_key.s != 'WATCHLIST_DEFINITIONS' or
2381 not isinstance(first_value, ast.Dict)):
2382 return (
2383 'The first entry of the dict in WATCHLISTS file must be '
2384 'WATCHLIST_DEFINITIONS dict')
2385
2386 if (not isinstance(second_key, ast.Str) or
2387 second_key.s != 'WATCHLISTS' or
2388 not isinstance(second_value, ast.Dict)):
2389 return (
2390 'The second entry of the dict in WATCHLISTS file must be '
2391 'WATCHLISTS dict')
2392
2393 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132394
2395
2396def _CheckWATCHLISTS(input_api, output_api):
2397 for f in input_api.AffectedFiles(include_deletes=False):
2398 if f.LocalPath() == 'WATCHLISTS':
2399 contents = input_api.ReadFile(f, 'r')
2400
2401 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202402 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132403 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202404 # Get an AST tree for it and scan the tree for detailed style checking.
2405 expression = input_api.ast.parse(
2406 contents, filename='WATCHLISTS', mode='eval')
2407 except ValueError as e:
2408 return [output_api.PresubmitError(
2409 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2410 except SyntaxError as e:
2411 return [output_api.PresubmitError(
2412 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2413 except TypeError as e:
2414 return [output_api.PresubmitError(
2415 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132416
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202417 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2418 if result is not None:
2419 return [output_api.PresubmitError(result)]
2420 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132421
2422 return []
2423
2424
dgnaa68d5e2015-06-10 10:08:222425def _AndroidSpecificOnUploadChecks(input_api, output_api):
2426 """Groups checks that target android code."""
2427 results = []
dgnaa68d5e2015-06-10 10:08:222428 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222429 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292430 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062431 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2432 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422433 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182434 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222435 return results
2436
2437
[email protected]22c9bd72011-03-27 16:47:392438def _CommonChecks(input_api, output_api):
2439 """Checks common to both upload and commit."""
2440 results = []
2441 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382442 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542443 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582444 results.extend(
2445 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192446 results.extend(
[email protected]760deea2013-12-10 19:33:492447 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542448 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182449 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522450 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222451 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442452 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592453 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062454 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122455 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182456 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222457 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302458 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492459 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032460 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492461 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442462 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272463 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072464 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542465 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442466 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392467 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552468 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042469 results.extend(
2470 input_api.canned_checks.CheckChangeHasNoTabs(
2471 input_api,
2472 output_api,
2473 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402474 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162475 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082476 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242477 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2478 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472479 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042480 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232481 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432482 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402483 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152484 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172485 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502486 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242487 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362488 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132489 results.extend(_CheckWATCHLISTS(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242490
2491 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2492 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2493 input_api, output_api,
2494 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382495 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392496 return results
[email protected]1f7b4172010-01-28 01:17:342497
[email protected]b337cb5b2011-01-23 21:24:052498
[email protected]b8079ae4a2012-12-05 19:56:492499def _CheckPatchFiles(input_api, output_api):
2500 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2501 if f.LocalPath().endswith(('.orig', '.rej'))]
2502 if problems:
2503 return [output_api.PresubmitError(
2504 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032505 else:
2506 return []
[email protected]b8079ae4a2012-12-05 19:56:492507
2508
Kent Tamura5a8755d2017-06-29 23:37:072509def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212510 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2511 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2512 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072513 include_re = input_api.re.compile(
2514 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2515 extension_re = input_api.re.compile(r'\.[a-z]+$')
2516 errors = []
2517 for f in input_api.AffectedFiles():
2518 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2519 continue
2520 found_line_number = None
2521 found_macro = None
2522 for line_num, line in f.ChangedContents():
2523 match = macro_re.search(line)
2524 if match:
2525 found_line_number = line_num
2526 found_macro = match.group(2)
2527 break
2528 if not found_line_number:
2529 continue
2530
2531 found_include = False
2532 for line in f.NewContents():
2533 if include_re.search(line):
2534 found_include = True
2535 break
2536 if found_include:
2537 continue
2538
2539 if not f.LocalPath().endswith('.h'):
2540 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2541 try:
2542 content = input_api.ReadFile(primary_header_path, 'r')
2543 if include_re.search(content):
2544 continue
2545 except IOError:
2546 pass
2547 errors.append('%s:%d %s macro is used without including build/'
2548 'build_config.h.'
2549 % (f.LocalPath(), found_line_number, found_macro))
2550 if errors:
2551 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2552 return []
2553
2554
[email protected]b00342e7f2013-03-26 16:21:542555def _DidYouMeanOSMacro(bad_macro):
2556 try:
2557 return {'A': 'OS_ANDROID',
2558 'B': 'OS_BSD',
2559 'C': 'OS_CHROMEOS',
2560 'F': 'OS_FREEBSD',
2561 'L': 'OS_LINUX',
2562 'M': 'OS_MACOSX',
2563 'N': 'OS_NACL',
2564 'O': 'OS_OPENBSD',
2565 'P': 'OS_POSIX',
2566 'S': 'OS_SOLARIS',
2567 'W': 'OS_WIN'}[bad_macro[3].upper()]
2568 except KeyError:
2569 return ''
2570
2571
2572def _CheckForInvalidOSMacrosInFile(input_api, f):
2573 """Check for sensible looking, totally invalid OS macros."""
2574 preprocessor_statement = input_api.re.compile(r'^\s*#')
2575 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2576 results = []
2577 for lnum, line in f.ChangedContents():
2578 if preprocessor_statement.search(line):
2579 for match in os_macro.finditer(line):
2580 if not match.group(1) in _VALID_OS_MACROS:
2581 good = _DidYouMeanOSMacro(match.group(1))
2582 did_you_mean = ' (did you mean %s?)' % good if good else ''
2583 results.append(' %s:%d %s%s' % (f.LocalPath(),
2584 lnum,
2585 match.group(1),
2586 did_you_mean))
2587 return results
2588
2589
2590def _CheckForInvalidOSMacros(input_api, output_api):
2591 """Check all affected files for invalid OS macros."""
2592 bad_macros = []
2593 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472594 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542595 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2596
2597 if not bad_macros:
2598 return []
2599
2600 return [output_api.PresubmitError(
2601 'Possibly invalid OS macro[s] found. Please fix your code\n'
2602 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2603
lliabraa35bab3932014-10-01 12:16:442604
2605def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2606 """Check all affected files for invalid "if defined" macros."""
2607 ALWAYS_DEFINED_MACROS = (
2608 "TARGET_CPU_PPC",
2609 "TARGET_CPU_PPC64",
2610 "TARGET_CPU_68K",
2611 "TARGET_CPU_X86",
2612 "TARGET_CPU_ARM",
2613 "TARGET_CPU_MIPS",
2614 "TARGET_CPU_SPARC",
2615 "TARGET_CPU_ALPHA",
2616 "TARGET_IPHONE_SIMULATOR",
2617 "TARGET_OS_EMBEDDED",
2618 "TARGET_OS_IPHONE",
2619 "TARGET_OS_MAC",
2620 "TARGET_OS_UNIX",
2621 "TARGET_OS_WIN32",
2622 )
2623 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2624 results = []
2625 for lnum, line in f.ChangedContents():
2626 for match in ifdef_macro.finditer(line):
2627 if match.group(1) in ALWAYS_DEFINED_MACROS:
2628 always_defined = ' %s is always defined. ' % match.group(1)
2629 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2630 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2631 lnum,
2632 always_defined,
2633 did_you_mean))
2634 return results
2635
2636
2637def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2638 """Check all affected files for invalid "if defined" macros."""
2639 bad_macros = []
2640 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212641 if f.LocalPath().startswith('third_party/sqlite/'):
2642 continue
lliabraa35bab3932014-10-01 12:16:442643 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2644 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2645
2646 if not bad_macros:
2647 return []
2648
2649 return [output_api.PresubmitError(
2650 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2651 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2652 bad_macros)]
2653
2654
mlamouria82272622014-09-16 18:45:042655def _CheckForIPCRules(input_api, output_api):
2656 """Check for same IPC rules described in
2657 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2658 """
2659 base_pattern = r'IPC_ENUM_TRAITS\('
2660 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2661 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2662
2663 problems = []
2664 for f in input_api.AffectedSourceFiles(None):
2665 local_path = f.LocalPath()
2666 if not local_path.endswith('.h'):
2667 continue
2668 for line_number, line in f.ChangedContents():
2669 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2670 problems.append(
2671 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2672
2673 if problems:
2674 return [output_api.PresubmitPromptWarning(
2675 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2676 else:
2677 return []
2678
[email protected]b00342e7f2013-03-26 16:21:542679
mostynbb639aca52015-01-07 20:31:232680def _CheckForWindowsLineEndings(input_api, output_api):
2681 """Check source code and known ascii text files for Windows style line
2682 endings.
2683 """
earthdok1b5e0ee2015-03-10 15:19:102684 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232685
2686 file_inclusion_pattern = (
2687 known_text_files,
2688 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2689 )
2690
2691 filter = lambda f: input_api.FilterSourceFile(
2692 f, white_list=file_inclusion_pattern, black_list=None)
2693 files = [f.LocalPath() for f in
2694 input_api.AffectedSourceFiles(filter)]
2695
2696 problems = []
2697
2698 for file in files:
2699 fp = open(file, 'r')
2700 for line in fp:
2701 if line.endswith('\r\n'):
2702 problems.append(file)
2703 break
2704 fp.close()
2705
2706 if problems:
2707 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2708 'these files to contain Windows style line endings?\n' +
2709 '\n'.join(problems))]
2710
2711 return []
2712
2713
pastarmovj89f7ee12016-09-20 14:58:132714def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2715 lint_filters=None, verbose_level=None):
2716 """Checks that all source files use SYSLOG properly."""
2717 syslog_files = []
2718 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562719 for line_number, line in f.ChangedContents():
2720 if 'SYSLOG' in line:
2721 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2722
pastarmovj89f7ee12016-09-20 14:58:132723 if syslog_files:
2724 return [output_api.PresubmitPromptWarning(
2725 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2726 ' calls.\nFiles to check:\n', items=syslog_files)]
2727 return []
2728
2729
[email protected]1f7b4172010-01-28 01:17:342730def CheckChangeOnUpload(input_api, output_api):
2731 results = []
2732 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472733 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282734 results.extend(
jam93a6ee792017-02-08 23:59:222735 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192736 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222737 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132738 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162739 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542740 return results
[email protected]ca8d1982009-02-19 16:33:122741
2742
[email protected]1bfb8322014-04-23 01:02:412743def GetTryServerMasterForBot(bot):
2744 """Returns the Try Server master for the given bot.
2745
[email protected]0bb112362014-07-26 04:38:322746 It tries to guess the master from the bot name, but may still fail
2747 and return None. There is no longer a default master.
2748 """
2749 # Potentially ambiguous bot names are listed explicitly.
2750 master_map = {
tandriie5587792016-07-14 00:34:502751 'chromium_presubmit': 'master.tryserver.chromium.linux',
2752 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412753 }
[email protected]0bb112362014-07-26 04:38:322754 master = master_map.get(bot)
2755 if not master:
wnwen4fbaab82016-05-25 12:54:362756 if 'android' in bot:
tandriie5587792016-07-14 00:34:502757 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362758 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502759 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322760 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502761 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322762 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502763 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322764 return master
[email protected]1bfb8322014-04-23 01:02:412765
2766
[email protected]ca8d1982009-02-19 16:33:122767def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542768 results = []
[email protected]1f7b4172010-01-28 01:17:342769 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542770 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272771 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342772 input_api,
2773 output_api,
[email protected]2fdd1f362013-01-16 03:56:032774 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272775
jam93a6ee792017-02-08 23:59:222776 results.extend(
2777 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542778 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2779 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412780 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2781 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542782 return results