blob: f5c4d863641e35006bb76fb181ee4e853ba4e96e [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d19842009-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]ca8d19842009-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[\\\/].*",
primiano0166ccc82015-10-06 12:12:2819 r"^third_party[\\\/]WebKit[\\\/].*",
[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]ca8d19842009-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]ca8d19842009-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
[email protected]127f18ec2012-06-16 05:05:5968_BANNED_OBJC_FUNCTIONS = (
69 (
70 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2071 (
72 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5973 'prohibited. Please use CrTrackingArea instead.',
74 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
75 ),
76 False,
77 ),
78 (
[email protected]eaae1972014-04-16 04:17:2679 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2080 (
81 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5982 'instead.',
83 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
84 ),
85 False,
86 ),
87 (
88 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2089 (
90 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5991 'Please use |convertPoint:(point) fromView:nil| instead.',
92 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
93 ),
94 True,
95 ),
96 (
97 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:2098 (
99 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59100 'Please use |convertPoint:(point) toView:nil| instead.',
101 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
102 ),
103 True,
104 ),
105 (
106 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20107 (
108 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59109 'Please use |convertRect:(point) fromView:nil| instead.',
110 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
111 ),
112 True,
113 ),
114 (
115 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20116 (
117 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59118 'Please use |convertRect:(point) toView:nil| instead.',
119 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
120 ),
121 True,
122 ),
123 (
124 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20125 (
126 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59127 'Please use |convertSize:(point) fromView:nil| instead.',
128 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
129 ),
130 True,
131 ),
132 (
133 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20134 (
135 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59136 'Please use |convertSize:(point) toView:nil| instead.',
137 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
138 ),
139 True,
140 ),
jif65398702016-10-27 10:19:48141 (
142 r"/\s+UTF8String\s*]",
143 (
144 'The use of -[NSString UTF8String] is dangerous as it can return null',
145 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
146 'Please use |SysNSStringToUTF8| instead.',
147 ),
148 True,
149 ),
[email protected]127f18ec2012-06-16 05:05:59150)
151
152
153_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20154 # Make sure that gtest's FRIEND_TEST() macro is not used; the
155 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30156 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20157 (
thomasandersone7caaa9b2017-03-29 19:22:53158 r'\bNULL\b',
159 (
160 'New code should not use NULL. Use nullptr instead.',
161 ),
162 True,
163 (),
164 ),
165 (
[email protected]23e6cbc2012-06-16 18:51:20166 'FRIEND_TEST(',
167 (
[email protected]e3c945502012-06-26 20:01:49168 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20169 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
170 ),
171 False,
[email protected]7345da02012-11-27 14:31:49172 (),
[email protected]23e6cbc2012-06-16 18:51:20173 ),
174 (
thomasanderson4b569052016-09-14 20:15:53175 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
176 (
177 'Chrome clients wishing to select events on X windows should use',
178 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
179 'you are selecting events from the GPU process, or if you are using',
180 'an XDisplay other than gfx::GetXDisplay().',
181 ),
182 True,
183 (
184 r"^ui[\\\/]gl[\\\/].*\.cc$",
185 r"^media[\\\/]gpu[\\\/].*\.cc$",
186 r"^gpu[\\\/].*\.cc$",
187 ),
188 ),
189 (
thomasandersone043e3ce2017-06-08 00:43:20190 r'XInternAtom|xcb_intern_atom',
191 (
thomasanderson11aa41d2017-06-08 22:22:38192 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20193 ),
194 True,
195 (
thomasanderson11aa41d2017-06-08 22:22:38196 r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$",
197 r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20198 r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$",
199 ),
200 ),
201 (
[email protected]23e6cbc2012-06-16 18:51:20202 'ScopedAllowIO',
203 (
satoruxe1396f8a2017-06-01 06:40:39204 'New production code should not use ScopedAllowIO (using it in',
Marijn Kruisselbrink085ef092017-07-12 23:56:55205 'tests is fine). Post a task to a MayBlock task runner instead.',
[email protected]23e6cbc2012-06-16 18:51:20206 ),
[email protected]e3c945502012-06-26 20:01:49207 True,
[email protected]7345da02012-11-27 14:31:49208 (
Marijn Kruisselbrink085ef092017-07-12 23:56:55209 r"^.*(browser|unit)(|_)test[a-z_]*\.cc$",
hajimehoshi2acea432017-03-08 08:55:37210 r"^base[\\\/]memory[\\\/]shared_memory_posix\.cc$",
rayb0088ee52017-04-26 22:35:08211 r"^base[\\\/]process[\\\/]internal_aix\.cc$",
nyad2c548b2015-12-09 03:22:32212 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10213 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
tfarina0923ac52015-01-07 03:21:22214 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
rdevlin.cronin62018a12017-06-22 17:34:06215 r"^chrome[\\\/]browser[\\\/]extensions[\\\/]" +
216 r"chrome_test_extension_loader.cc$",
sky0e07a142016-03-25 21:27:31217 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
philipj3f9d5bde2014-08-28 14:09:09218 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49219 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
220 r"test_info_extractor\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41221 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
222 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25223 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
miu8e0e80c2017-05-31 03:35:57224 r"^media[\\\/]cast[\\\/]test[\\\/]utility[\\\/]" +
225 r"standalone_cast_environment\.cc$",
jamesra03ae492014-10-03 04:26:48226 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
227 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01228 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25229 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
230 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
231 r"embedded_test_server\.cc$",
232 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
233 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54234 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
sergeyu2c41f9842016-12-10 01:45:16235 r"^remoting[\\\/]protocol[\\\/]webrtc_transport\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53236 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
237 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45238 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
239 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
240 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
241 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
242 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49243 ),
[email protected]23e6cbc2012-06-16 18:51:20244 ),
[email protected]52657f62013-05-20 05:30:31245 (
tomhudsone2c14d552016-05-26 17:07:46246 'setMatrixClip',
247 (
248 'Overriding setMatrixClip() is prohibited; ',
249 'the base function is deprecated. ',
250 ),
251 True,
252 (),
253 ),
254 (
[email protected]52657f62013-05-20 05:30:31255 'SkRefPtr',
256 (
257 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22258 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31259 ),
260 True,
261 (),
262 ),
263 (
264 'SkAutoRef',
265 (
266 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22267 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31268 ),
269 True,
270 (),
271 ),
272 (
273 'SkAutoTUnref',
274 (
275 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22276 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31277 ),
278 True,
279 (),
280 ),
281 (
282 'SkAutoUnref',
283 (
284 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
285 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22286 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31287 ),
288 True,
289 (),
290 ),
[email protected]d89eec82013-12-03 14:10:59291 (
292 r'/HANDLE_EINTR\(.*close',
293 (
294 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
295 'descriptor will be closed, and it is incorrect to retry the close.',
296 'Either call close directly and ignore its return value, or wrap close',
297 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
298 ),
299 True,
300 (),
301 ),
302 (
303 r'/IGNORE_EINTR\((?!.*close)',
304 (
305 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
306 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
307 ),
308 True,
309 (
310 # Files that #define IGNORE_EINTR.
311 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
312 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
313 ),
314 ),
[email protected]ec5b3f02014-04-04 18:43:43315 (
316 r'/v8::Extension\(',
317 (
318 'Do not introduce new v8::Extensions into the code base, use',
319 'gin::Wrappable instead. See http://crbug.com/334679',
320 ),
321 True,
[email protected]f55c90ee62014-04-12 00:50:03322 (
joaodasilva718f87672014-08-30 09:25:49323 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03324 ),
[email protected]ec5b3f02014-04-04 18:43:43325 ),
skyostilf9469f72015-04-20 10:38:52326 (
jame2d1a952016-04-02 00:27:10327 '#pragma comment(lib,',
328 (
329 'Specify libraries to link with in build files and not in the source.',
330 ),
331 True,
332 (),
333 ),
fdorayc4ac18d2017-05-01 21:39:59334 (
335 'BrowserThread::GetBlockingPool',
336 (
337 'Use base/task_scheduler/post_task.h instead of the blocking pool. See',
338 'mapping between both APIs in content/public/browser/browser_thread.h.',
339 'For questions, contact base/task_scheduler/OWNERS.',
340 ),
341 True,
342 (),
343 ),
gabd52c912a2017-05-11 04:15:59344 (
Gabriel Charette664e4482017-06-13 19:55:29345 'BrowserThread::(FILE|FILE_USER_BLOCKING|DB|PROCESS_LAUNCHER|CACHE)',
346 (
347 'The non-UI/IO BrowserThreads are deprecated, please migrate this',
348 'code to TaskScheduler. See https://goo.gl/mDSxKl for details.',
349 'For questions, contact base/task_scheduler/OWNERS.',
350 ),
351 True,
352 (),
353 ),
354 (
gabd52c912a2017-05-11 04:15:59355 'base::SequenceChecker',
356 (
357 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
358 ),
359 False,
360 (),
361 ),
362 (
363 'base::ThreadChecker',
364 (
365 'Consider using THREAD_CHECKER macros instead of the class directly.',
366 ),
367 False,
368 (),
369 ),
dbeamb6f4fde2017-06-15 04:03:06370 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06371 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
372 (
373 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
374 'deprecated (http://crbug.com/634507). Please avoid converting away',
375 'from the Time types in Chromium code, especially if any math is',
376 'being done on time values. For interfacing with platform/library',
377 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
378 'type converter methods instead. For faking TimeXXX values (for unit',
379 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
380 'other use cases, please contact base/time/OWNERS.',
381 ),
382 False,
383 (),
384 ),
385 (
dbeamb6f4fde2017-06-15 04:03:06386 'CallJavascriptFunctionUnsafe',
387 (
388 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
389 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
390 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
391 ),
392 False,
393 (
394 r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$',
395 r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$',
396 r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$',
397 ),
398 ),
dskiba1474c2bfd62017-07-20 02:19:24399 (
400 'leveldb::DB::Open',
401 (
402 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
403 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
404 "Chrome's tracing, making their memory usage visible.",
405 ),
406 True,
407 (
408 r'^third_party/leveldatabase/.*\.(cc|h)$',
409 ),
410 )
[email protected]127f18ec2012-06-16 05:05:59411)
412
wnwenbdc444e2016-05-25 13:44:15413
mlamouria82272622014-09-16 18:45:04414_IPC_ENUM_TRAITS_DEPRECATED = (
415 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
416 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
417
[email protected]127f18ec2012-06-16 05:05:59418
[email protected]b00342e7f2013-03-26 16:21:54419_VALID_OS_MACROS = (
420 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08421 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54422 'OS_ANDROID',
423 'OS_BSD',
424 'OS_CAT', # For testing.
425 'OS_CHROMEOS',
426 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37427 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54428 'OS_IOS',
429 'OS_LINUX',
430 'OS_MACOSX',
431 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21432 'OS_NACL_NONSFI',
433 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12434 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54435 'OS_OPENBSD',
436 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37437 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54438 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54439 'OS_WIN',
440)
441
442
agrievef32bcc72016-04-04 14:57:40443_ANDROID_SPECIFIC_PYDEPS_FILES = [
444 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04445 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58446 'build/secondary/third_party/android_platform/'
447 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19448 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40449]
450
wnwenbdc444e2016-05-25 13:44:15451
agrievef32bcc72016-04-04 14:57:40452_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40453]
454
wnwenbdc444e2016-05-25 13:44:15455
agrievef32bcc72016-04-04 14:57:40456_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
457
458
[email protected]55459852011-08-10 15:17:19459def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
460 """Attempts to prevent use of functions intended only for testing in
461 non-testing code. For now this is just a best-effort implementation
462 that ignores header files and may have some false positives. A
463 better implementation would probably need a proper C++ parser.
464 """
465 # We only scan .cc files and the like, as the declaration of
466 # for-testing functions in header files are hard to distinguish from
467 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44468 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19469
jochenc0d4808c2015-07-27 09:25:42470 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19471 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09472 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19473 exclusion_pattern = input_api.re.compile(
474 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
475 base_function_pattern, base_function_pattern))
476
477 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44478 black_list = (_EXCLUDED_PATHS +
479 _TEST_CODE_EXCLUDED_PATHS +
480 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19481 return input_api.FilterSourceFile(
482 affected_file,
483 white_list=(file_inclusion_pattern, ),
484 black_list=black_list)
485
486 problems = []
487 for f in input_api.AffectedSourceFiles(FilterFile):
488 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24489 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03490 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46491 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03492 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19493 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03494 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19495
496 if problems:
[email protected]f7051d52013-04-02 18:31:42497 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03498 else:
499 return []
[email protected]55459852011-08-10 15:17:19500
501
[email protected]10689ca2011-09-02 02:31:54502def _CheckNoIOStreamInHeaders(input_api, output_api):
503 """Checks to make sure no .h files include <iostream>."""
504 files = []
505 pattern = input_api.re.compile(r'^#include\s*<iostream>',
506 input_api.re.MULTILINE)
507 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
508 if not f.LocalPath().endswith('.h'):
509 continue
510 contents = input_api.ReadFile(f)
511 if pattern.search(contents):
512 files.append(f)
513
514 if len(files):
yolandyandaabc6d2016-04-18 18:29:39515 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06516 'Do not #include <iostream> in header files, since it inserts static '
517 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54518 '#include <ostream>. See http://crbug.com/94794',
519 files) ]
520 return []
521
522
[email protected]72df4e782012-06-21 16:28:18523def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52524 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18525 problems = []
526 for f in input_api.AffectedFiles():
527 if (not f.LocalPath().endswith(('.cc', '.mm'))):
528 continue
529
530 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04531 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18532 problems.append(' %s:%d' % (f.LocalPath(), line_num))
533
534 if not problems:
535 return []
536 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
537 '\n'.join(problems))]
538
539
danakj61c1aa22015-10-26 19:55:52540def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57541 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52542 errors = []
543 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
544 input_api.re.MULTILINE)
545 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
546 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
547 continue
548 for lnum, line in f.ChangedContents():
549 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17550 errors.append(output_api.PresubmitError(
551 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57552 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17553 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52554 return errors
555
556
mcasasb7440c282015-02-04 14:52:19557def _FindHistogramNameInLine(histogram_name, line):
558 """Tries to find a histogram name or prefix in a line."""
559 if not "affected-histogram" in line:
560 return histogram_name in line
561 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
562 # the histogram_name.
563 if not '"' in line:
564 return False
565 histogram_prefix = line.split('\"')[1]
566 return histogram_prefix in histogram_name
567
568
569def _CheckUmaHistogramChanges(input_api, output_api):
570 """Check that UMA histogram names in touched lines can still be found in other
571 lines of the patch or in histograms.xml. Note that this check would not catch
572 the reverse: changes in histograms.xml not matched in the code itself."""
573 touched_histograms = []
574 histograms_xml_modifications = []
575 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
576 for f in input_api.AffectedFiles():
577 # If histograms.xml itself is modified, keep the modified lines for later.
578 if f.LocalPath().endswith(('histograms.xml')):
579 histograms_xml_modifications = f.ChangedContents()
580 continue
581 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
582 continue
583 for line_num, line in f.ChangedContents():
584 found = pattern.search(line)
585 if found:
586 touched_histograms.append([found.group(1), f, line_num])
587
588 # Search for the touched histogram names in the local modifications to
589 # histograms.xml, and, if not found, on the base histograms.xml file.
590 unmatched_histograms = []
591 for histogram_info in touched_histograms:
592 histogram_name_found = False
593 for line_num, line in histograms_xml_modifications:
594 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
595 if histogram_name_found:
596 break
597 if not histogram_name_found:
598 unmatched_histograms.append(histogram_info)
599
eromanb90c82e7e32015-04-01 15:13:49600 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19601 problems = []
602 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49603 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19604 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45605 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19606 histogram_name_found = False
607 for line in histograms_xml:
608 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
609 if histogram_name_found:
610 break
611 if not histogram_name_found:
612 problems.append(' [%s:%d] %s' %
613 (f.LocalPath(), line_num, histogram_name))
614
615 if not problems:
616 return []
617 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
618 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49619 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19620
wnwenbdc444e2016-05-25 13:44:15621
yolandyandaabc6d2016-04-18 18:29:39622def _CheckFlakyTestUsage(input_api, output_api):
623 """Check that FlakyTest annotation is our own instead of the android one"""
624 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
625 files = []
626 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
627 if f.LocalPath().endswith('Test.java'):
628 if pattern.search(input_api.ReadFile(f)):
629 files.append(f)
630 if len(files):
631 return [output_api.PresubmitError(
632 'Use org.chromium.base.test.util.FlakyTest instead of '
633 'android.test.FlakyTest',
634 files)]
635 return []
mcasasb7440c282015-02-04 14:52:19636
wnwenbdc444e2016-05-25 13:44:15637
[email protected]8ea5d4b2011-09-13 21:49:22638def _CheckNoNewWStrings(input_api, output_api):
639 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27640 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22641 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20642 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57643 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34644 '/win/' in f.LocalPath() or
645 'chrome_elf' in f.LocalPath() or
646 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20647 continue
[email protected]8ea5d4b2011-09-13 21:49:22648
[email protected]a11dbe9b2012-08-07 01:32:58649 allowWString = False
[email protected]b5c24292011-11-28 14:38:20650 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58651 if 'presubmit: allow wstring' in line:
652 allowWString = True
653 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27654 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58655 allowWString = False
656 else:
657 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22658
[email protected]55463aa62011-10-12 00:48:27659 if not problems:
660 return []
661 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58662 ' If you are calling a cross-platform API that accepts a wstring, '
663 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27664 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22665
666
[email protected]2a8ac9c2011-10-19 17:20:44667def _CheckNoDEPSGIT(input_api, output_api):
668 """Make sure .DEPS.git is never modified manually."""
669 if any(f.LocalPath().endswith('.DEPS.git') for f in
670 input_api.AffectedFiles()):
671 return [output_api.PresubmitError(
672 'Never commit changes to .DEPS.git. This file is maintained by an\n'
673 'automated system based on what\'s in DEPS and your changes will be\n'
674 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34675 '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:44676 'for more information')]
677 return []
678
679
tandriief664692014-09-23 14:51:47680def _CheckValidHostsInDEPS(input_api, output_api):
681 """Checks that DEPS file deps are from allowed_hosts."""
682 # Run only if DEPS file has been modified to annoy fewer bystanders.
683 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
684 return []
685 # Outsource work to gclient verify
686 try:
687 input_api.subprocess.check_output(['gclient', 'verify'])
688 return []
689 except input_api.subprocess.CalledProcessError, error:
690 return [output_api.PresubmitError(
691 'DEPS file must have only git dependencies.',
692 long_text=error.output)]
693
694
[email protected]127f18ec2012-06-16 05:05:59695def _CheckNoBannedFunctions(input_api, output_api):
696 """Make sure that banned functions are not used."""
697 warnings = []
698 errors = []
699
wnwenbdc444e2016-05-25 13:44:15700 def IsBlacklisted(affected_file, blacklist):
701 local_path = affected_file.LocalPath()
702 for item in blacklist:
703 if input_api.re.match(item, local_path):
704 return True
705 return False
706
707 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
708 matched = False
709 if func_name[0:1] == '/':
710 regex = func_name[1:]
711 if input_api.re.search(regex, line):
712 matched = True
713 elif func_name in line:
dchenge07de812016-06-20 19:27:17714 matched = True
wnwenbdc444e2016-05-25 13:44:15715 if matched:
dchenge07de812016-06-20 19:27:17716 problems = warnings
wnwenbdc444e2016-05-25 13:44:15717 if error:
dchenge07de812016-06-20 19:27:17718 problems = errors
wnwenbdc444e2016-05-25 13:44:15719 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
720 for message_line in message:
721 problems.append(' %s' % message_line)
722
[email protected]127f18ec2012-06-16 05:05:59723 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
724 for f in input_api.AffectedFiles(file_filter=file_filter):
725 for line_num, line in f.ChangedContents():
726 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15727 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59728
729 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
730 for f in input_api.AffectedFiles(file_filter=file_filter):
731 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49732 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49733 if IsBlacklisted(f, excluded_paths):
734 continue
wnwenbdc444e2016-05-25 13:44:15735 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59736
737 result = []
738 if (warnings):
739 result.append(output_api.PresubmitPromptWarning(
740 'Banned functions were used.\n' + '\n'.join(warnings)))
741 if (errors):
742 result.append(output_api.PresubmitError(
743 'Banned functions were used.\n' + '\n'.join(errors)))
744 return result
745
746
[email protected]6c063c62012-07-11 19:11:06747def _CheckNoPragmaOnce(input_api, output_api):
748 """Make sure that banned functions are not used."""
749 files = []
750 pattern = input_api.re.compile(r'^#pragma\s+once',
751 input_api.re.MULTILINE)
752 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
753 if not f.LocalPath().endswith('.h'):
754 continue
755 contents = input_api.ReadFile(f)
756 if pattern.search(contents):
757 files.append(f)
758
759 if files:
760 return [output_api.PresubmitError(
761 'Do not use #pragma once in header files.\n'
762 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
763 files)]
764 return []
765
[email protected]127f18ec2012-06-16 05:05:59766
[email protected]e7479052012-09-19 00:26:12767def _CheckNoTrinaryTrueFalse(input_api, output_api):
768 """Checks to make sure we don't introduce use of foo ? true : false."""
769 problems = []
770 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
771 for f in input_api.AffectedFiles():
772 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
773 continue
774
775 for line_num, line in f.ChangedContents():
776 if pattern.match(line):
777 problems.append(' %s:%d' % (f.LocalPath(), line_num))
778
779 if not problems:
780 return []
781 return [output_api.PresubmitPromptWarning(
782 'Please consider avoiding the "? true : false" pattern if possible.\n' +
783 '\n'.join(problems))]
784
785
[email protected]55f9f382012-07-31 11:02:18786def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28787 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18788 change. Breaking - rules is an error, breaking ! rules is a
789 warning.
790 """
mohan.reddyf21db962014-10-16 12:26:47791 import sys
[email protected]55f9f382012-07-31 11:02:18792 # We need to wait until we have an input_api object and use this
793 # roundabout construct to import checkdeps because this file is
794 # eval-ed and thus doesn't have __file__.
795 original_sys_path = sys.path
796 try:
797 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47798 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18799 import checkdeps
800 from cpp_checker import CppChecker
rhalavati08acd232017-04-03 07:23:28801 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18802 from rules import Rule
803 finally:
804 # Restore sys.path to what it was before.
805 sys.path = original_sys_path
806
807 added_includes = []
rhalavati08acd232017-04-03 07:23:28808 added_imports = []
[email protected]55f9f382012-07-31 11:02:18809 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28810 if CppChecker.IsCppFile(f.LocalPath()):
811 changed_lines = [line for line_num, line in f.ChangedContents()]
812 added_includes.append([f.LocalPath(), changed_lines])
813 elif ProtoChecker.IsProtoFile(f.LocalPath()):
814 changed_lines = [line for line_num, line in f.ChangedContents()]
815 added_imports.append([f.LocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18816
[email protected]26385172013-05-09 23:11:35817 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18818
819 error_descriptions = []
820 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28821 error_subjects = set()
822 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18823 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
824 added_includes):
825 description_with_path = '%s\n %s' % (path, rule_description)
826 if rule_type == Rule.DISALLOW:
827 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28828 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18829 else:
830 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28831 warning_subjects.add("#includes")
832
833 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
834 added_imports):
835 description_with_path = '%s\n %s' % (path, rule_description)
836 if rule_type == Rule.DISALLOW:
837 error_descriptions.append(description_with_path)
838 error_subjects.add("imports")
839 else:
840 warning_descriptions.append(description_with_path)
841 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18842
843 results = []
844 if error_descriptions:
845 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28846 'You added one or more %s that violate checkdeps rules.'
847 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18848 error_descriptions))
849 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42850 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28851 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18852 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28853 '%s? See relevant DEPS file(s) for details and contacts.' %
854 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18855 warning_descriptions))
856 return results
857
858
[email protected]fbcafe5a2012-08-08 15:31:22859def _CheckFilePermissions(input_api, output_api):
860 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15861 if input_api.platform == 'win32':
862 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29863 checkperms_tool = input_api.os_path.join(
864 input_api.PresubmitLocalPath(),
865 'tools', 'checkperms', 'checkperms.py')
866 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47867 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22868 for f in input_api.AffectedFiles():
869 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11870 try:
871 input_api.subprocess.check_output(args)
872 return []
873 except input_api.subprocess.CalledProcessError as error:
874 return [output_api.PresubmitError(
875 'checkperms.py failed:',
876 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22877
878
robertocn832f5992017-01-04 19:01:30879def _CheckTeamTags(input_api, output_api):
880 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
881 checkteamtags_tool = input_api.os_path.join(
882 input_api.PresubmitLocalPath(),
883 'tools', 'checkteamtags', 'checkteamtags.py')
884 args = [input_api.python_executable, checkteamtags_tool,
885 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22886 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30887 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
888 'OWNERS']
889 try:
890 if files:
891 input_api.subprocess.check_output(args + files)
892 return []
893 except input_api.subprocess.CalledProcessError as error:
894 return [output_api.PresubmitError(
895 'checkteamtags.py failed:',
896 long_text=error.output)]
897
898
[email protected]c8278b32012-10-30 20:35:49899def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
900 """Makes sure we don't include ui/aura/window_property.h
901 in header files.
902 """
903 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
904 errors = []
905 for f in input_api.AffectedFiles():
906 if not f.LocalPath().endswith('.h'):
907 continue
908 for line_num, line in f.ChangedContents():
909 if pattern.match(line):
910 errors.append(' %s:%d' % (f.LocalPath(), line_num))
911
912 results = []
913 if errors:
914 results.append(output_api.PresubmitError(
915 'Header files should not include ui/aura/window_property.h', errors))
916 return results
917
918
[email protected]70ca77752012-11-20 03:45:03919def _CheckForVersionControlConflictsInFile(input_api, f):
920 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
921 errors = []
922 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23923 if f.LocalPath().endswith('.md'):
924 # First-level headers in markdown look a lot like version control
925 # conflict markers. http://daringfireball.net/projects/markdown/basics
926 continue
[email protected]70ca77752012-11-20 03:45:03927 if pattern.match(line):
928 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
929 return errors
930
931
932def _CheckForVersionControlConflicts(input_api, output_api):
933 """Usually this is not intentional and will cause a compile failure."""
934 errors = []
935 for f in input_api.AffectedFiles():
936 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
937
938 results = []
939 if errors:
940 results.append(output_api.PresubmitError(
941 'Version control conflict markers found, please resolve.', errors))
942 return results
943
estadee17314a02017-01-12 16:22:16944def _CheckGoogleSupportAnswerUrl(input_api, output_api):
945 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
946 errors = []
947 for f in input_api.AffectedFiles():
948 for line_num, line in f.ChangedContents():
949 if pattern.search(line):
950 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
951
952 results = []
953 if errors:
954 results.append(output_api.PresubmitPromptWarning(
955 'Found Google support URL addressed by answer number. Please replace with '
956 'a p= identifier instead. See crbug.com/679462\n', errors))
957 return results
958
[email protected]70ca77752012-11-20 03:45:03959
[email protected]06e6d0ff2012-12-11 01:36:44960def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
961 def FilterFile(affected_file):
962 """Filter function for use with input_api.AffectedSourceFiles,
963 below. This filters out everything except non-test files from
964 top-level directories that generally speaking should not hard-code
965 service URLs (e.g. src/android_webview/, src/content/ and others).
966 """
967 return input_api.FilterSourceFile(
968 affected_file,
[email protected]78bb39d62012-12-11 15:11:56969 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44970 black_list=(_EXCLUDED_PATHS +
971 _TEST_CODE_EXCLUDED_PATHS +
972 input_api.DEFAULT_BLACK_LIST))
973
reillyi38965732015-11-16 18:27:33974 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
975 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:46976 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
977 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:44978 problems = [] # items are (filename, line_number, line)
979 for f in input_api.AffectedSourceFiles(FilterFile):
980 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:46981 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:44982 problems.append((f.LocalPath(), line_num, line))
983
984 if problems:
[email protected]f7051d52013-04-02 18:31:42985 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44986 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:58987 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:44988 [' %s:%d: %s' % (
989 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03990 else:
991 return []
[email protected]06e6d0ff2012-12-11 01:36:44992
993
[email protected]d2530012013-01-25 16:39:27994def _CheckNoAbbreviationInPngFileName(input_api, output_api):
995 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:31996 The native_client_sdk directory is excluded because it has auto-generated PNG
997 files for documentation.
[email protected]d2530012013-01-25 16:39:27998 """
[email protected]d2530012013-01-25 16:39:27999 errors = []
binji0dcdf342014-12-12 18:32:311000 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1001 black_list = (r'^native_client_sdk[\\\/]',)
1002 file_filter = lambda f: input_api.FilterSourceFile(
1003 f, white_list=white_list, black_list=black_list)
1004 for f in input_api.AffectedFiles(include_deletes=False,
1005 file_filter=file_filter):
1006 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271007
1008 results = []
1009 if errors:
1010 results.append(output_api.PresubmitError(
1011 'The name of PNG files should not have abbreviations. \n'
1012 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1013 'Contact [email protected] if you have questions.', errors))
1014 return results
1015
1016
Daniel Cheng4dcdb6b2017-04-13 08:30:171017def _ExtractAddRulesFromParsedDeps(parsed_deps):
1018 """Extract the rules that add dependencies from a parsed DEPS file.
1019
1020 Args:
1021 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1022 add_rules = set()
1023 add_rules.update([
1024 rule[1:] for rule in parsed_deps.get('include_rules', [])
1025 if rule.startswith('+') or rule.startswith('!')
1026 ])
1027 for specific_file, rules in parsed_deps.get('specific_include_rules',
1028 {}).iteritems():
1029 add_rules.update([
1030 rule[1:] for rule in rules
1031 if rule.startswith('+') or rule.startswith('!')
1032 ])
1033 return add_rules
1034
1035
1036def _ParseDeps(contents):
1037 """Simple helper for parsing DEPS files."""
1038 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171039 class _VarImpl:
1040
1041 def __init__(self, local_scope):
1042 self._local_scope = local_scope
1043
1044 def Lookup(self, var_name):
1045 """Implements the Var syntax."""
1046 try:
1047 return self._local_scope['vars'][var_name]
1048 except KeyError:
1049 raise Exception('Var is not defined: %s' % var_name)
1050
1051 local_scope = {}
1052 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171053 'Var': _VarImpl(local_scope).Lookup,
1054 }
1055 exec contents in global_scope, local_scope
1056 return local_scope
1057
1058
1059def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081060 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411061 a set of DEPS entries that we should look up.
1062
1063 For a directory (rather than a specific filename) we fake a path to
1064 a specific filename by adding /DEPS. This is chosen as a file that
1065 will seldom or never be subject to per-file include_rules.
1066 """
[email protected]2b438d62013-11-14 17:54:141067 # We ignore deps entries on auto-generated directories.
1068 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081069
Daniel Cheng4dcdb6b2017-04-13 08:30:171070 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1071 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1072
1073 added_deps = new_deps.difference(old_deps)
1074
[email protected]2b438d62013-11-14 17:54:141075 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171076 for added_dep in added_deps:
1077 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1078 continue
1079 # Assume that a rule that ends in .h is a rule for a specific file.
1080 if added_dep.endswith('.h'):
1081 results.add(added_dep)
1082 else:
1083 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081084 return results
1085
1086
[email protected]e871964c2013-05-13 14:14:551087def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1088 """When a dependency prefixed with + is added to a DEPS file, we
1089 want to make sure that the change is reviewed by an OWNER of the
1090 target file or directory, to avoid layering violations from being
1091 introduced. This check verifies that this happens.
1092 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171093 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241094
1095 file_filter = lambda f: not input_api.re.match(
1096 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1097 for f in input_api.AffectedFiles(include_deletes=False,
1098 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551099 filename = input_api.os_path.basename(f.LocalPath())
1100 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171101 virtual_depended_on_files.update(_CalculateAddedDeps(
1102 input_api.os_path,
1103 '\n'.join(f.OldContents()),
1104 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551105
[email protected]e871964c2013-05-13 14:14:551106 if not virtual_depended_on_files:
1107 return []
1108
1109 if input_api.is_committing:
1110 if input_api.tbr:
1111 return [output_api.PresubmitNotifyResult(
1112 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271113 if input_api.dry_run:
1114 return [output_api.PresubmitNotifyResult(
1115 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551116 if not input_api.change.issue:
1117 return [output_api.PresubmitError(
1118 "DEPS approval by OWNERS check failed: this change has "
1119 "no Rietveld issue number, so we can't check it for approvals.")]
1120 output = output_api.PresubmitError
1121 else:
1122 output = output_api.PresubmitNotifyResult
1123
1124 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501125 owner_email, reviewers = (
1126 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1127 input_api,
1128 owners_db.email_regexp,
1129 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551130
1131 owner_email = owner_email or input_api.change.author_email
1132
[email protected]de4f7d22013-05-23 14:27:461133 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511134 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461135 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551136 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1137 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411138
1139 # We strip the /DEPS part that was added by
1140 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1141 # directory.
1142 def StripDeps(path):
1143 start_deps = path.rfind('/DEPS')
1144 if start_deps != -1:
1145 return path[:start_deps]
1146 else:
1147 return path
1148 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551149 for path in missing_files]
1150
1151 if unapproved_dependencies:
1152 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151153 output('You need LGTM from owners of depends-on paths in DEPS that were '
1154 'modified in this CL:\n %s' %
1155 '\n '.join(sorted(unapproved_dependencies)))]
1156 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1157 output_list.append(output(
1158 'Suggested missing target path OWNERS:\n %s' %
1159 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551160 return output_list
1161
1162 return []
1163
1164
[email protected]85218562013-11-22 07:41:401165def _CheckSpamLogging(input_api, output_api):
1166 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1167 black_list = (_EXCLUDED_PATHS +
1168 _TEST_CODE_EXCLUDED_PATHS +
1169 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501170 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191171 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481172 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461173 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121174 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1175 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581176 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591177 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161178 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031179 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151180 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1181 r"^chromecast[\\\/]",
1182 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481183 r"^components[\\\/]browser_watcher[\\\/]"
1184 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311185 r"^components[\\\/]html_viewer[\\\/]"
1186 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461187 # TODO(peter): Remove this exception. https://crbug.com/534537
1188 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1189 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251190 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1191 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241192 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111193 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151194 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111195 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521196 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501197 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361198 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311199 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131200 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001201 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441202 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451203 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021204 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351205 r"dump_file_system.cc$",
1206 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401207 source_file_filter = lambda x: input_api.FilterSourceFile(
1208 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1209
thomasanderson625d3932017-03-29 07:16:581210 log_info = set([])
1211 printf = set([])
[email protected]85218562013-11-22 07:41:401212
1213 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581214 for _, line in f.ChangedContents():
1215 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1216 log_info.add(f.LocalPath())
1217 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1218 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371219
thomasanderson625d3932017-03-29 07:16:581220 if input_api.re.search(r"\bprintf\(", line):
1221 printf.add(f.LocalPath())
1222 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1223 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401224
1225 if log_info:
1226 return [output_api.PresubmitError(
1227 'These files spam the console log with LOG(INFO):',
1228 items=log_info)]
1229 if printf:
1230 return [output_api.PresubmitError(
1231 'These files spam the console log with printf/fprintf:',
1232 items=printf)]
1233 return []
1234
1235
[email protected]49aa76a2013-12-04 06:59:161236def _CheckForAnonymousVariables(input_api, output_api):
1237 """These types are all expected to hold locks while in scope and
1238 so should never be anonymous (which causes them to be immediately
1239 destroyed)."""
1240 they_who_must_be_named = [
1241 'base::AutoLock',
1242 'base::AutoReset',
1243 'base::AutoUnlock',
1244 'SkAutoAlphaRestore',
1245 'SkAutoBitmapShaderInstall',
1246 'SkAutoBlitterChoose',
1247 'SkAutoBounderCommit',
1248 'SkAutoCallProc',
1249 'SkAutoCanvasRestore',
1250 'SkAutoCommentBlock',
1251 'SkAutoDescriptor',
1252 'SkAutoDisableDirectionCheck',
1253 'SkAutoDisableOvalCheck',
1254 'SkAutoFree',
1255 'SkAutoGlyphCache',
1256 'SkAutoHDC',
1257 'SkAutoLockColors',
1258 'SkAutoLockPixels',
1259 'SkAutoMalloc',
1260 'SkAutoMaskFreeImage',
1261 'SkAutoMutexAcquire',
1262 'SkAutoPathBoundsUpdate',
1263 'SkAutoPDFRelease',
1264 'SkAutoRasterClipValidate',
1265 'SkAutoRef',
1266 'SkAutoTime',
1267 'SkAutoTrace',
1268 'SkAutoUnref',
1269 ]
1270 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1271 # bad: base::AutoLock(lock.get());
1272 # not bad: base::AutoLock lock(lock.get());
1273 bad_pattern = input_api.re.compile(anonymous)
1274 # good: new base::AutoLock(lock.get())
1275 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1276 errors = []
1277
1278 for f in input_api.AffectedFiles():
1279 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1280 continue
1281 for linenum, line in f.ChangedContents():
1282 if bad_pattern.search(line) and not good_pattern.search(line):
1283 errors.append('%s:%d' % (f.LocalPath(), linenum))
1284
1285 if errors:
1286 return [output_api.PresubmitError(
1287 'These lines create anonymous variables that need to be named:',
1288 items=errors)]
1289 return []
1290
1291
[email protected]999261d2014-03-03 20:08:081292def _CheckUserActionUpdate(input_api, output_api):
1293 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521294 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081295 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521296 # If actions.xml is already included in the changelist, the PRESUBMIT
1297 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081298 return []
1299
[email protected]999261d2014-03-03 20:08:081300 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1301 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521302 current_actions = None
[email protected]999261d2014-03-03 20:08:081303 for f in input_api.AffectedFiles(file_filter=file_filter):
1304 for line_num, line in f.ChangedContents():
1305 match = input_api.re.search(action_re, line)
1306 if match:
[email protected]2f92dec2014-03-07 19:21:521307 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1308 # loaded only once.
1309 if not current_actions:
1310 with open('tools/metrics/actions/actions.xml') as actions_f:
1311 current_actions = actions_f.read()
1312 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081313 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521314 action = 'name="{0}"'.format(action_name)
1315 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081316 return [output_api.PresubmitPromptWarning(
1317 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521318 'tools/metrics/actions/actions.xml. Please run '
1319 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081320 % (f.LocalPath(), line_num, action_name))]
1321 return []
1322
1323
[email protected]99171a92014-06-03 08:44:471324def _GetJSONParseError(input_api, filename, eat_comments=True):
1325 try:
1326 contents = input_api.ReadFile(filename)
1327 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131328 import sys
1329 original_sys_path = sys.path
1330 try:
1331 sys.path = sys.path + [input_api.os_path.join(
1332 input_api.PresubmitLocalPath(),
1333 'tools', 'json_comment_eater')]
1334 import json_comment_eater
1335 finally:
1336 sys.path = original_sys_path
1337 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471338
1339 input_api.json.loads(contents)
1340 except ValueError as e:
1341 return e
1342 return None
1343
1344
1345def _GetIDLParseError(input_api, filename):
1346 try:
1347 contents = input_api.ReadFile(filename)
1348 idl_schema = input_api.os_path.join(
1349 input_api.PresubmitLocalPath(),
1350 'tools', 'json_schema_compiler', 'idl_schema.py')
1351 process = input_api.subprocess.Popen(
1352 [input_api.python_executable, idl_schema],
1353 stdin=input_api.subprocess.PIPE,
1354 stdout=input_api.subprocess.PIPE,
1355 stderr=input_api.subprocess.PIPE,
1356 universal_newlines=True)
1357 (_, error) = process.communicate(input=contents)
1358 return error or None
1359 except ValueError as e:
1360 return e
1361
1362
1363def _CheckParseErrors(input_api, output_api):
1364 """Check that IDL and JSON files do not contain syntax errors."""
1365 actions = {
1366 '.idl': _GetIDLParseError,
1367 '.json': _GetJSONParseError,
1368 }
1369 # These paths contain test data and other known invalid JSON files.
1370 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491371 r'test[\\\/]data[\\\/]',
1372 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471373 ]
1374 # Most JSON files are preprocessed and support comments, but these do not.
1375 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491376 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471377 ]
1378 # Only run IDL checker on files in these directories.
1379 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491380 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1381 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471382 ]
1383
1384 def get_action(affected_file):
1385 filename = affected_file.LocalPath()
1386 return actions.get(input_api.os_path.splitext(filename)[1])
1387
1388 def MatchesFile(patterns, path):
1389 for pattern in patterns:
1390 if input_api.re.search(pattern, path):
1391 return True
1392 return False
1393
1394 def FilterFile(affected_file):
1395 action = get_action(affected_file)
1396 if not action:
1397 return False
1398 path = affected_file.LocalPath()
1399
1400 if MatchesFile(excluded_patterns, path):
1401 return False
1402
1403 if (action == _GetIDLParseError and
1404 not MatchesFile(idl_included_patterns, path)):
1405 return False
1406 return True
1407
1408 results = []
1409 for affected_file in input_api.AffectedFiles(
1410 file_filter=FilterFile, include_deletes=False):
1411 action = get_action(affected_file)
1412 kwargs = {}
1413 if (action == _GetJSONParseError and
1414 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1415 kwargs['eat_comments'] = False
1416 parse_error = action(input_api,
1417 affected_file.AbsoluteLocalPath(),
1418 **kwargs)
1419 if parse_error:
1420 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1421 (affected_file.LocalPath(), parse_error)))
1422 return results
1423
1424
[email protected]760deea2013-12-10 19:33:491425def _CheckJavaStyle(input_api, output_api):
1426 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471427 import sys
[email protected]760deea2013-12-10 19:33:491428 original_sys_path = sys.path
1429 try:
1430 sys.path = sys.path + [input_api.os_path.join(
1431 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1432 import checkstyle
1433 finally:
1434 # Restore sys.path to what it was before.
1435 sys.path = original_sys_path
1436
1437 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091438 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511439 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491440
1441
dchenge07de812016-06-20 19:27:171442def _CheckIpcOwners(input_api, output_api):
1443 """Checks that affected files involving IPC have an IPC OWNERS rule.
1444
1445 Whether or not a file affects IPC is determined by a simple whitelist of
1446 filename patterns."""
1447 file_patterns = [
palmerb19a0932017-01-24 04:00:311448 # Legacy IPC:
dchenge07de812016-06-20 19:27:171449 '*_messages.cc',
1450 '*_messages*.h',
1451 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311452 # Mojo IPC:
dchenge07de812016-06-20 19:27:171453 '*.mojom',
1454 '*_struct_traits*.*',
1455 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311456 '*.typemap',
1457 # Android native IPC:
1458 '*.aidl',
1459 # Blink uses a different file naming convention:
1460 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171461 '*StructTraits*.*',
1462 '*TypeConverter*.*',
1463 ]
1464
scottmg7a6ed5ba2016-11-04 18:22:041465 # These third_party directories do not contain IPCs, but contain files
1466 # matching the above patterns, which trigger false positives.
1467 exclude_paths = [
1468 'third_party/crashpad/*',
1469 ]
1470
dchenge07de812016-06-20 19:27:171471 # Dictionary mapping an OWNERS file path to Patterns.
1472 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1473 # rules ) to a PatternEntry.
1474 # PatternEntry is a dictionary with two keys:
1475 # - 'files': the files that are matched by this pattern
1476 # - 'rules': the per-file rules needed for this pattern
1477 # For example, if we expect OWNERS file to contain rules for *.mojom and
1478 # *_struct_traits*.*, Patterns might look like this:
1479 # {
1480 # '*.mojom': {
1481 # 'files': ...,
1482 # 'rules': [
1483 # 'per-file *.mojom=set noparent',
1484 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1485 # ],
1486 # },
1487 # '*_struct_traits*.*': {
1488 # 'files': ...,
1489 # 'rules': [
1490 # 'per-file *_struct_traits*.*=set noparent',
1491 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1492 # ],
1493 # },
1494 # }
1495 to_check = {}
1496
1497 # Iterate through the affected files to see what we actually need to check
1498 # for. We should only nag patch authors about per-file rules if a file in that
1499 # directory would match that pattern. If a directory only contains *.mojom
1500 # files and no *_messages*.h files, we should only nag about rules for
1501 # *.mojom files.
rockot51249332016-06-23 16:32:251502 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171503 for pattern in file_patterns:
1504 if input_api.fnmatch.fnmatch(
1505 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041506 skip = False
1507 for exclude in exclude_paths:
1508 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1509 skip = True
1510 break
1511 if skip:
1512 continue
dchenge07de812016-06-20 19:27:171513 owners_file = input_api.os_path.join(
1514 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1515 if owners_file not in to_check:
1516 to_check[owners_file] = {}
1517 if pattern not in to_check[owners_file]:
1518 to_check[owners_file][pattern] = {
1519 'files': [],
1520 'rules': [
1521 'per-file %s=set noparent' % pattern,
1522 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1523 ]
1524 }
1525 to_check[owners_file][pattern]['files'].append(f)
1526 break
1527
1528 # Now go through the OWNERS files we collected, filtering out rules that are
1529 # already present in that OWNERS file.
1530 for owners_file, patterns in to_check.iteritems():
1531 try:
1532 with file(owners_file) as f:
1533 lines = set(f.read().splitlines())
1534 for entry in patterns.itervalues():
1535 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1536 ]
1537 except IOError:
1538 # No OWNERS file, so all the rules are definitely missing.
1539 continue
1540
1541 # All the remaining lines weren't found in OWNERS files, so emit an error.
1542 errors = []
1543 for owners_file, patterns in to_check.iteritems():
1544 missing_lines = []
1545 files = []
1546 for pattern, entry in patterns.iteritems():
1547 missing_lines.extend(entry['rules'])
1548 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1549 if missing_lines:
1550 errors.append(
Daniel Cheng52111692017-06-14 08:00:591551 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171552 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1553
1554 results = []
1555 if errors:
vabrf5ce3bf92016-07-11 14:52:411556 if input_api.is_committing:
1557 output = output_api.PresubmitError
1558 else:
1559 output = output_api.PresubmitPromptWarning
1560 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591561 'Found OWNERS files that need to be updated for IPC security ' +
1562 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171563 long_text='\n\n'.join(errors)))
1564
1565 return results
1566
1567
jbriance9e12f162016-11-25 07:57:501568def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311569 """Checks that added or removed lines in non third party affected
1570 header files do not lead to new useless class or struct forward
1571 declaration.
jbriance9e12f162016-11-25 07:57:501572 """
1573 results = []
1574 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1575 input_api.re.MULTILINE)
1576 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1577 input_api.re.MULTILINE)
1578 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311579 if (f.LocalPath().startswith('third_party') and
1580 not f.LocalPath().startswith('third_party/WebKit') and
1581 not f.LocalPath().startswith('third_party\\WebKit')):
1582 continue
1583
jbriance9e12f162016-11-25 07:57:501584 if not f.LocalPath().endswith('.h'):
1585 continue
1586
1587 contents = input_api.ReadFile(f)
1588 fwd_decls = input_api.re.findall(class_pattern, contents)
1589 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1590
1591 useless_fwd_decls = []
1592 for decl in fwd_decls:
1593 count = sum(1 for _ in input_api.re.finditer(
1594 r'\b%s\b' % input_api.re.escape(decl), contents))
1595 if count == 1:
1596 useless_fwd_decls.append(decl)
1597
1598 if not useless_fwd_decls:
1599 continue
1600
1601 for line in f.GenerateScmDiff().splitlines():
1602 if (line.startswith('-') and not line.startswith('--') or
1603 line.startswith('+') and not line.startswith('++')):
1604 for decl in useless_fwd_decls:
1605 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1606 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241607 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501608 (f.LocalPath(), decl)))
1609 useless_fwd_decls.remove(decl)
1610
1611 return results
1612
1613
dskiba88634f4e2015-08-14 23:03:291614def _CheckAndroidToastUsage(input_api, output_api):
1615 """Checks that code uses org.chromium.ui.widget.Toast instead of
1616 android.widget.Toast (Chromium Toast doesn't force hardware
1617 acceleration on low-end devices, saving memory).
1618 """
1619 toast_import_pattern = input_api.re.compile(
1620 r'^import android\.widget\.Toast;$')
1621
1622 errors = []
1623
1624 sources = lambda affected_file: input_api.FilterSourceFile(
1625 affected_file,
1626 black_list=(_EXCLUDED_PATHS +
1627 _TEST_CODE_EXCLUDED_PATHS +
1628 input_api.DEFAULT_BLACK_LIST +
1629 (r'^chromecast[\\\/].*',
1630 r'^remoting[\\\/].*')),
1631 white_list=(r'.*\.java$',))
1632
1633 for f in input_api.AffectedSourceFiles(sources):
1634 for line_num, line in f.ChangedContents():
1635 if toast_import_pattern.search(line):
1636 errors.append("%s:%d" % (f.LocalPath(), line_num))
1637
1638 results = []
1639
1640 if errors:
1641 results.append(output_api.PresubmitError(
1642 'android.widget.Toast usage is detected. Android toasts use hardware'
1643 ' acceleration, and can be\ncostly on low-end devices. Please use'
1644 ' org.chromium.ui.widget.Toast instead.\n'
1645 'Contact [email protected] if you have any questions.',
1646 errors))
1647
1648 return results
1649
1650
dgnaa68d5e2015-06-10 10:08:221651def _CheckAndroidCrLogUsage(input_api, output_api):
1652 """Checks that new logs using org.chromium.base.Log:
1653 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511654 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221655 """
pkotwicza1dd0b002016-05-16 14:41:041656
torne89540622017-03-24 19:41:301657 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041658 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301659 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041660 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301661 # WebView license viewer code cannot depend on //base; used in stub APK.
1662 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1663 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041664 ]
1665
dgnaa68d5e2015-06-10 10:08:221666 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121667 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1668 class_in_base_pattern = input_api.re.compile(
1669 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1670 has_some_log_import_pattern = input_api.re.compile(
1671 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221672 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121673 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221674 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511675 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221676 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221677
Vincent Scheib16d7b272015-09-15 18:09:071678 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221679 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041680 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1681 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121682
dgnaa68d5e2015-06-10 10:08:221683 tag_decl_errors = []
1684 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121685 tag_errors = []
dgn38736db2015-09-18 19:20:511686 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121687 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221688
1689 for f in input_api.AffectedSourceFiles(sources):
1690 file_content = input_api.ReadFile(f)
1691 has_modified_logs = False
1692
1693 # Per line checks
dgn87d9fb62015-06-12 09:15:121694 if (cr_log_import_pattern.search(file_content) or
1695 (class_in_base_pattern.search(file_content) and
1696 not has_some_log_import_pattern.search(file_content))):
1697 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221698 for line_num, line in f.ChangedContents():
1699
1700 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121701 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221702 if match:
1703 has_modified_logs = True
1704
1705 # Make sure it uses "TAG"
1706 if not match.group('tag') == 'TAG':
1707 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121708 else:
1709 # Report non cr Log function calls in changed lines
1710 for line_num, line in f.ChangedContents():
1711 if log_call_pattern.search(line):
1712 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221713
1714 # Per file checks
1715 if has_modified_logs:
1716 # Make sure the tag is using the "cr" prefix and is not too long
1717 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511718 tag_name = match.group('name') if match else None
1719 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221720 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511721 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221722 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511723 elif '.' in tag_name:
1724 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221725
1726 results = []
1727 if tag_decl_errors:
1728 results.append(output_api.PresubmitPromptWarning(
1729 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511730 '"private static final String TAG = "<package tag>".\n'
1731 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221732 tag_decl_errors))
1733
1734 if tag_length_errors:
1735 results.append(output_api.PresubmitError(
1736 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511737 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221738 tag_length_errors))
1739
1740 if tag_errors:
1741 results.append(output_api.PresubmitPromptWarning(
1742 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1743 tag_errors))
1744
dgn87d9fb62015-06-12 09:15:121745 if util_log_errors:
dgn4401aa52015-04-29 16:26:171746 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121747 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1748 util_log_errors))
1749
dgn38736db2015-09-18 19:20:511750 if tag_with_dot_errors:
1751 results.append(output_api.PresubmitPromptWarning(
1752 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1753 tag_with_dot_errors))
1754
dgn4401aa52015-04-29 16:26:171755 return results
1756
1757
yolandyan45001472016-12-21 21:12:421758def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1759 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1760 deprecated_annotation_import_pattern = input_api.re.compile(
1761 r'^import android\.test\.suitebuilder\.annotation\..*;',
1762 input_api.re.MULTILINE)
1763 sources = lambda x: input_api.FilterSourceFile(
1764 x, white_list=(r'.*\.java$',), black_list=None)
1765 errors = []
1766 for f in input_api.AffectedFiles(sources):
1767 for line_num, line in f.ChangedContents():
1768 if deprecated_annotation_import_pattern.search(line):
1769 errors.append("%s:%d" % (f.LocalPath(), line_num))
1770
1771 results = []
1772 if errors:
1773 results.append(output_api.PresubmitError(
1774 'Annotations in android.test.suitebuilder.annotation have been'
1775 ' deprecated since API level 24. Please use android.support.test.filters'
1776 ' from //third_party/android_support_test_runner:runner_java instead.'
1777 ' Contact [email protected] if you have any questions.', errors))
1778 return results
1779
1780
agrieve7b6479d82015-10-07 14:24:221781def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1782 """Checks if MDPI assets are placed in a correct directory."""
1783 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1784 ('/res/drawable/' in f.LocalPath() or
1785 '/res/drawable-ldrtl/' in f.LocalPath()))
1786 errors = []
1787 for f in input_api.AffectedFiles(include_deletes=False,
1788 file_filter=file_filter):
1789 errors.append(' %s' % f.LocalPath())
1790
1791 results = []
1792 if errors:
1793 results.append(output_api.PresubmitError(
1794 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1795 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1796 '/res/drawable-ldrtl/.\n'
1797 'Contact [email protected] if you have questions.', errors))
1798 return results
1799
1800
agrievef32bcc72016-04-04 14:57:401801class PydepsChecker(object):
1802 def __init__(self, input_api, pydeps_files):
1803 self._file_cache = {}
1804 self._input_api = input_api
1805 self._pydeps_files = pydeps_files
1806
1807 def _LoadFile(self, path):
1808 """Returns the list of paths within a .pydeps file relative to //."""
1809 if path not in self._file_cache:
1810 with open(path) as f:
1811 self._file_cache[path] = f.read()
1812 return self._file_cache[path]
1813
1814 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1815 """Returns an interable of paths within the .pydep, relativized to //."""
1816 os_path = self._input_api.os_path
1817 pydeps_dir = os_path.dirname(pydeps_path)
1818 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1819 if not l.startswith('*'))
1820 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1821
1822 def _CreateFilesToPydepsMap(self):
1823 """Returns a map of local_path -> list_of_pydeps."""
1824 ret = {}
1825 for pydep_local_path in self._pydeps_files:
1826 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1827 ret.setdefault(path, []).append(pydep_local_path)
1828 return ret
1829
1830 def ComputeAffectedPydeps(self):
1831 """Returns an iterable of .pydeps files that might need regenerating."""
1832 affected_pydeps = set()
1833 file_to_pydeps_map = None
1834 for f in self._input_api.AffectedFiles(include_deletes=True):
1835 local_path = f.LocalPath()
1836 if local_path == 'DEPS':
1837 return self._pydeps_files
1838 elif local_path.endswith('.pydeps'):
1839 if local_path in self._pydeps_files:
1840 affected_pydeps.add(local_path)
1841 elif local_path.endswith('.py'):
1842 if file_to_pydeps_map is None:
1843 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1844 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1845 return affected_pydeps
1846
1847 def DetermineIfStale(self, pydeps_path):
1848 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411849 import difflib
agrievef32bcc72016-04-04 14:57:401850 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1851 cmd = old_pydeps_data[1][1:].strip()
1852 new_pydeps_data = self._input_api.subprocess.check_output(
1853 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411854 old_contents = old_pydeps_data[2:]
1855 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401856 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411857 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401858
1859
1860def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1861 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001862 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281863 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1864 # Mac, so skip it on other platforms.
1865 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001866 return []
agrievef32bcc72016-04-04 14:57:401867 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1868 is_android = input_api.os_path.exists('third_party/android_tools')
1869 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1870 results = []
1871 # First, check for new / deleted .pydeps.
1872 for f in input_api.AffectedFiles(include_deletes=True):
1873 if f.LocalPath().endswith('.pydeps'):
1874 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1875 results.append(output_api.PresubmitError(
1876 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1877 'remove %s' % f.LocalPath()))
1878 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1879 results.append(output_api.PresubmitError(
1880 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1881 'include %s' % f.LocalPath()))
1882
1883 if results:
1884 return results
1885
1886 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1887
1888 for pydep_path in checker.ComputeAffectedPydeps():
1889 try:
phajdan.jr0d9878552016-11-04 10:49:411890 result = checker.DetermineIfStale(pydep_path)
1891 if result:
1892 cmd, diff = result
agrievef32bcc72016-04-04 14:57:401893 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:411894 'File is stale: %s\nDiff (apply to fix):\n%s\n'
1895 'To regenerate, run:\n\n %s' %
1896 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:401897 except input_api.subprocess.CalledProcessError as error:
1898 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1899 long_text=error.output)]
1900
1901 return results
1902
1903
glidere61efad2015-02-18 17:39:431904def _CheckSingletonInHeaders(input_api, output_api):
1905 """Checks to make sure no header files have |Singleton<|."""
1906 def FileFilter(affected_file):
1907 # It's ok for base/memory/singleton.h to have |Singleton<|.
1908 black_list = (_EXCLUDED_PATHS +
1909 input_api.DEFAULT_BLACK_LIST +
1910 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1911 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1912
sergeyu34d21222015-09-16 00:11:441913 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431914 files = []
1915 for f in input_api.AffectedSourceFiles(FileFilter):
1916 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1917 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1918 contents = input_api.ReadFile(f)
1919 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241920 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431921 pattern.search(line)):
1922 files.append(f)
1923 break
1924
1925 if files:
yolandyandaabc6d2016-04-18 18:29:391926 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441927 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431928 'Please move them to an appropriate source file so that the ' +
1929 'template gets instantiated in a single compilation unit.',
1930 files) ]
1931 return []
1932
1933
[email protected]fd20b902014-05-09 02:14:531934_DEPRECATED_CSS = [
1935 # Values
1936 ( "-webkit-box", "flex" ),
1937 ( "-webkit-inline-box", "inline-flex" ),
1938 ( "-webkit-flex", "flex" ),
1939 ( "-webkit-inline-flex", "inline-flex" ),
1940 ( "-webkit-min-content", "min-content" ),
1941 ( "-webkit-max-content", "max-content" ),
1942
1943 # Properties
1944 ( "-webkit-background-clip", "background-clip" ),
1945 ( "-webkit-background-origin", "background-origin" ),
1946 ( "-webkit-background-size", "background-size" ),
1947 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:441948 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:531949
1950 # Functions
1951 ( "-webkit-gradient", "gradient" ),
1952 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1953 ( "-webkit-linear-gradient", "linear-gradient" ),
1954 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1955 ( "-webkit-radial-gradient", "radial-gradient" ),
1956 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1957]
1958
dbeam1ec68ac2016-12-15 05:22:241959def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:531960 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251961 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341962 documentation and iOS CSS for dom distiller
1963 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251964 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531965 results = []
dbeam070cfe62014-10-22 06:44:021966 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251967 black_list = (_EXCLUDED_PATHS +
1968 _TEST_CODE_EXCLUDED_PATHS +
1969 input_api.DEFAULT_BLACK_LIST +
1970 (r"^chrome/common/extensions/docs",
1971 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341972 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:441973 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251974 r"^native_client_sdk"))
1975 file_filter = lambda f: input_api.FilterSourceFile(
1976 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531977 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1978 for line_num, line in fpath.ChangedContents():
1979 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021980 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531981 results.append(output_api.PresubmitError(
1982 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1983 (fpath.LocalPath(), line_num, deprecated_value, value)))
1984 return results
1985
mohan.reddyf21db962014-10-16 12:26:471986
dbeam070cfe62014-10-22 06:44:021987_DEPRECATED_JS = [
1988 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1989 ( "__defineGetter__", "Object.defineProperty" ),
1990 ( "__defineSetter__", "Object.defineProperty" ),
1991]
1992
dbeam1ec68ac2016-12-15 05:22:241993def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:021994 """Make sure that we don't use deprecated JS in Chrome code."""
1995 results = []
1996 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1997 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1998 input_api.DEFAULT_BLACK_LIST)
1999 file_filter = lambda f: input_api.FilterSourceFile(
2000 f, white_list=file_inclusion_pattern, black_list=black_list)
2001 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2002 for lnum, line in fpath.ChangedContents():
2003 for (deprecated, replacement) in _DEPRECATED_JS:
2004 if deprecated in line:
2005 results.append(output_api.PresubmitError(
2006 "%s:%d: Use of deprecated JS %s, use %s instead" %
2007 (fpath.LocalPath(), lnum, deprecated, replacement)))
2008 return results
2009
dpapadd651231d82017-07-21 02:44:472010def _CheckForRiskyJsArrowFunction(line_number, line):
2011 if ' => ' in line:
2012 return "line %d, is using an => (arrow) function\n %s\n" % (
2013 line_number, line)
2014 return ''
2015
2016def _CheckForRiskyJsConstLet(input_api, line_number, line):
2017 if input_api.re.match('^\s*(const|let)\s', line):
2018 return "line %d, is using const/let keyword\n %s\n" % (
2019 line_number, line)
2020 return ''
dbeam070cfe62014-10-22 06:44:022021
dbeam1ec68ac2016-12-15 05:22:242022def _CheckForRiskyJsFeatures(input_api, output_api):
2023 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
2024 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js)
2025
dpapadd651231d82017-07-21 02:44:472026 results = []
dbeam1ec68ac2016-12-15 05:22:242027 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472028 arrow_error_lines = []
2029 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242030 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472031 arrow_error_lines += filter(None, [
2032 _CheckForRiskyJsArrowFunction(lnum, line),
2033 ])
dbeam1ec68ac2016-12-15 05:22:242034
dpapadd651231d82017-07-21 02:44:472035 const_let_error_lines += filter(None, [
2036 _CheckForRiskyJsConstLet(input_api, lnum, line),
2037 ])
dbeam1ec68ac2016-12-15 05:22:242038
dpapadd651231d82017-07-21 02:44:472039 if arrow_error_lines:
2040 arrow_error_lines = map(
2041 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2042 results.append(
2043 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2044"""
2045Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242046%s
2047Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2048https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472049""" % f.LocalPath()
2050 ])))
dbeam1ec68ac2016-12-15 05:22:242051
dpapadd651231d82017-07-21 02:44:472052 if const_let_error_lines:
2053 const_let_error_lines = map(
2054 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2055 results.append(
2056 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2057"""
2058Use of const/let keywords detected in:
2059%s
2060Please ensure your code does not run on iOS9 because const/let is not fully
2061supported.
2062https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2063https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2064""" % f.LocalPath()
2065 ])))
2066
2067 return results
dbeam1ec68ac2016-12-15 05:22:242068
rlanday6802cf632017-05-30 17:48:362069def _CheckForRelativeIncludes(input_api, output_api):
2070 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2071 import sys
2072 original_sys_path = sys.path
2073 try:
2074 sys.path = sys.path + [input_api.os_path.join(
2075 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2076 from cpp_checker import CppChecker
2077 finally:
2078 # Restore sys.path to what it was before.
2079 sys.path = original_sys_path
2080
2081 bad_files = {}
2082 for f in input_api.AffectedFiles(include_deletes=False):
2083 if (f.LocalPath().startswith('third_party') and
2084 not f.LocalPath().startswith('third_party/WebKit') and
2085 not f.LocalPath().startswith('third_party\\WebKit')):
2086 continue
2087
2088 if not CppChecker.IsCppFile(f.LocalPath()):
2089 continue
2090
2091 relative_includes = [line for line_num, line in f.ChangedContents()
2092 if "#include" in line and "../" in line]
2093 if not relative_includes:
2094 continue
2095 bad_files[f.LocalPath()] = relative_includes
2096
2097 if not bad_files:
2098 return []
2099
2100 error_descriptions = []
2101 for file_path, bad_lines in bad_files.iteritems():
2102 error_description = file_path
2103 for line in bad_lines:
2104 error_description += '\n ' + line
2105 error_descriptions.append(error_description)
2106
2107 results = []
2108 results.append(output_api.PresubmitError(
2109 'You added one or more relative #include paths (including "../").\n'
2110 'These shouldn\'t be used because they can be used to include headers\n'
2111 'from code that\'s not correctly specified as a dependency in the\n'
2112 'relevant BUILD.gn file(s).',
2113 error_descriptions))
2114
2115 return results
2116
dgnaa68d5e2015-06-10 10:08:222117def _AndroidSpecificOnUploadChecks(input_api, output_api):
2118 """Groups checks that target android code."""
2119 results = []
dgnaa68d5e2015-06-10 10:08:222120 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222121 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292122 results.extend(_CheckAndroidToastUsage(input_api, output_api))
yolandyan45001472016-12-21 21:12:422123 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222124 return results
2125
2126
[email protected]22c9bd72011-03-27 16:47:392127def _CommonChecks(input_api, output_api):
2128 """Checks common to both upload and commit."""
2129 results = []
2130 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382131 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542132 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582133 results.extend(
2134 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192135 results.extend(
[email protected]760deea2013-12-10 19:33:492136 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542137 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182138 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522139 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222140 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442141 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592142 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062143 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122144 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182145 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222146 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302147 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492148 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032149 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492150 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442151 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272152 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072153 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542154 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442155 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392156 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552157 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042158 results.extend(
2159 input_api.canned_checks.CheckChangeHasNoTabs(
2160 input_api,
2161 output_api,
2162 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402163 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162164 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082165 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242166 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2167 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472168 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042169 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232170 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432171 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402172 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152173 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172174 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502175 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242176 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362177 results.extend(_CheckForRelativeIncludes(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242178
2179 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2180 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2181 input_api, output_api,
2182 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382183 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392184 return results
[email protected]1f7b4172010-01-28 01:17:342185
[email protected]b337cb5b2011-01-23 21:24:052186
[email protected]b8079ae4a2012-12-05 19:56:492187def _CheckPatchFiles(input_api, output_api):
2188 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2189 if f.LocalPath().endswith(('.orig', '.rej'))]
2190 if problems:
2191 return [output_api.PresubmitError(
2192 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032193 else:
2194 return []
[email protected]b8079ae4a2012-12-05 19:56:492195
2196
Kent Tamura5a8755d2017-06-29 23:37:072197def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212198 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2199 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2200 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072201 include_re = input_api.re.compile(
2202 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2203 extension_re = input_api.re.compile(r'\.[a-z]+$')
2204 errors = []
2205 for f in input_api.AffectedFiles():
2206 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2207 continue
2208 found_line_number = None
2209 found_macro = None
2210 for line_num, line in f.ChangedContents():
2211 match = macro_re.search(line)
2212 if match:
2213 found_line_number = line_num
2214 found_macro = match.group(2)
2215 break
2216 if not found_line_number:
2217 continue
2218
2219 found_include = False
2220 for line in f.NewContents():
2221 if include_re.search(line):
2222 found_include = True
2223 break
2224 if found_include:
2225 continue
2226
2227 if not f.LocalPath().endswith('.h'):
2228 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2229 try:
2230 content = input_api.ReadFile(primary_header_path, 'r')
2231 if include_re.search(content):
2232 continue
2233 except IOError:
2234 pass
2235 errors.append('%s:%d %s macro is used without including build/'
2236 'build_config.h.'
2237 % (f.LocalPath(), found_line_number, found_macro))
2238 if errors:
2239 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2240 return []
2241
2242
[email protected]b00342e7f2013-03-26 16:21:542243def _DidYouMeanOSMacro(bad_macro):
2244 try:
2245 return {'A': 'OS_ANDROID',
2246 'B': 'OS_BSD',
2247 'C': 'OS_CHROMEOS',
2248 'F': 'OS_FREEBSD',
2249 'L': 'OS_LINUX',
2250 'M': 'OS_MACOSX',
2251 'N': 'OS_NACL',
2252 'O': 'OS_OPENBSD',
2253 'P': 'OS_POSIX',
2254 'S': 'OS_SOLARIS',
2255 'W': 'OS_WIN'}[bad_macro[3].upper()]
2256 except KeyError:
2257 return ''
2258
2259
2260def _CheckForInvalidOSMacrosInFile(input_api, f):
2261 """Check for sensible looking, totally invalid OS macros."""
2262 preprocessor_statement = input_api.re.compile(r'^\s*#')
2263 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2264 results = []
2265 for lnum, line in f.ChangedContents():
2266 if preprocessor_statement.search(line):
2267 for match in os_macro.finditer(line):
2268 if not match.group(1) in _VALID_OS_MACROS:
2269 good = _DidYouMeanOSMacro(match.group(1))
2270 did_you_mean = ' (did you mean %s?)' % good if good else ''
2271 results.append(' %s:%d %s%s' % (f.LocalPath(),
2272 lnum,
2273 match.group(1),
2274 did_you_mean))
2275 return results
2276
2277
2278def _CheckForInvalidOSMacros(input_api, output_api):
2279 """Check all affected files for invalid OS macros."""
2280 bad_macros = []
2281 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472282 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542283 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2284
2285 if not bad_macros:
2286 return []
2287
2288 return [output_api.PresubmitError(
2289 'Possibly invalid OS macro[s] found. Please fix your code\n'
2290 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2291
lliabraa35bab3932014-10-01 12:16:442292
2293def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2294 """Check all affected files for invalid "if defined" macros."""
2295 ALWAYS_DEFINED_MACROS = (
2296 "TARGET_CPU_PPC",
2297 "TARGET_CPU_PPC64",
2298 "TARGET_CPU_68K",
2299 "TARGET_CPU_X86",
2300 "TARGET_CPU_ARM",
2301 "TARGET_CPU_MIPS",
2302 "TARGET_CPU_SPARC",
2303 "TARGET_CPU_ALPHA",
2304 "TARGET_IPHONE_SIMULATOR",
2305 "TARGET_OS_EMBEDDED",
2306 "TARGET_OS_IPHONE",
2307 "TARGET_OS_MAC",
2308 "TARGET_OS_UNIX",
2309 "TARGET_OS_WIN32",
2310 )
2311 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2312 results = []
2313 for lnum, line in f.ChangedContents():
2314 for match in ifdef_macro.finditer(line):
2315 if match.group(1) in ALWAYS_DEFINED_MACROS:
2316 always_defined = ' %s is always defined. ' % match.group(1)
2317 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2318 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2319 lnum,
2320 always_defined,
2321 did_you_mean))
2322 return results
2323
2324
2325def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2326 """Check all affected files for invalid "if defined" macros."""
2327 bad_macros = []
2328 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212329 if f.LocalPath().startswith('third_party/sqlite/'):
2330 continue
lliabraa35bab3932014-10-01 12:16:442331 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2332 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2333
2334 if not bad_macros:
2335 return []
2336
2337 return [output_api.PresubmitError(
2338 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2339 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2340 bad_macros)]
2341
2342
mlamouria82272622014-09-16 18:45:042343def _CheckForIPCRules(input_api, output_api):
2344 """Check for same IPC rules described in
2345 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2346 """
2347 base_pattern = r'IPC_ENUM_TRAITS\('
2348 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2349 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2350
2351 problems = []
2352 for f in input_api.AffectedSourceFiles(None):
2353 local_path = f.LocalPath()
2354 if not local_path.endswith('.h'):
2355 continue
2356 for line_number, line in f.ChangedContents():
2357 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2358 problems.append(
2359 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2360
2361 if problems:
2362 return [output_api.PresubmitPromptWarning(
2363 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2364 else:
2365 return []
2366
[email protected]b00342e7f2013-03-26 16:21:542367
mostynbb639aca52015-01-07 20:31:232368def _CheckForWindowsLineEndings(input_api, output_api):
2369 """Check source code and known ascii text files for Windows style line
2370 endings.
2371 """
earthdok1b5e0ee2015-03-10 15:19:102372 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232373
2374 file_inclusion_pattern = (
2375 known_text_files,
2376 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2377 )
2378
2379 filter = lambda f: input_api.FilterSourceFile(
2380 f, white_list=file_inclusion_pattern, black_list=None)
2381 files = [f.LocalPath() for f in
2382 input_api.AffectedSourceFiles(filter)]
2383
2384 problems = []
2385
2386 for file in files:
2387 fp = open(file, 'r')
2388 for line in fp:
2389 if line.endswith('\r\n'):
2390 problems.append(file)
2391 break
2392 fp.close()
2393
2394 if problems:
2395 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2396 'these files to contain Windows style line endings?\n' +
2397 '\n'.join(problems))]
2398
2399 return []
2400
2401
pastarmovj89f7ee12016-09-20 14:58:132402def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2403 lint_filters=None, verbose_level=None):
2404 """Checks that all source files use SYSLOG properly."""
2405 syslog_files = []
2406 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562407 for line_number, line in f.ChangedContents():
2408 if 'SYSLOG' in line:
2409 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2410
pastarmovj89f7ee12016-09-20 14:58:132411 if syslog_files:
2412 return [output_api.PresubmitPromptWarning(
2413 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2414 ' calls.\nFiles to check:\n', items=syslog_files)]
2415 return []
2416
2417
[email protected]1f7b4172010-01-28 01:17:342418def CheckChangeOnUpload(input_api, output_api):
2419 results = []
2420 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472421 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282422 results.extend(
jam93a6ee792017-02-08 23:59:222423 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192424 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222425 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132426 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162427 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542428 return results
[email protected]ca8d19842009-02-19 16:33:122429
2430
[email protected]1bfb8322014-04-23 01:02:412431def GetTryServerMasterForBot(bot):
2432 """Returns the Try Server master for the given bot.
2433
[email protected]0bb112362014-07-26 04:38:322434 It tries to guess the master from the bot name, but may still fail
2435 and return None. There is no longer a default master.
2436 """
2437 # Potentially ambiguous bot names are listed explicitly.
2438 master_map = {
tandriie5587792016-07-14 00:34:502439 'chromium_presubmit': 'master.tryserver.chromium.linux',
2440 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412441 }
[email protected]0bb112362014-07-26 04:38:322442 master = master_map.get(bot)
2443 if not master:
wnwen4fbaab82016-05-25 12:54:362444 if 'android' in bot:
tandriie5587792016-07-14 00:34:502445 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362446 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502447 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322448 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502449 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322450 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502451 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322452 return master
[email protected]1bfb8322014-04-23 01:02:412453
2454
Paweł Hajdan, Jr55083782014-12-19 20:32:562455def GetDefaultTryConfigs(bots):
2456 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012457 """
2458
Paweł Hajdan, Jr55083782014-12-19 20:32:562459 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412460
2461 # Build up the mapping from tryserver master to bot/test.
2462 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562463 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412464 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2465 return out
[email protected]38c6a512013-12-18 23:48:012466
2467
[email protected]ca8d19842009-02-19 16:33:122468def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542469 results = []
[email protected]1f7b4172010-01-28 01:17:342470 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542471 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272472 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342473 input_api,
2474 output_api,
[email protected]2fdd1f362013-01-16 03:56:032475 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272476
jam93a6ee792017-02-08 23:59:222477 results.extend(
2478 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542479 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2480 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412481 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2482 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542483 return results