blob: dee1ee4cdcba466c9485c7b1cd401717b6487314 [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[\\\/].*",
Kent Tamurae9b3a9ec2017-08-31 02:20:1919 r"^third_party[\\\/](WebKit|blink)[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
vapierb2053f542017-03-09 19:46:1026 r"tools[\\\/]md_browser[\\\/].*\.css$",
ehmaldonado78eee2ed2017-03-28 13:16:5427 # Test pages for WebRTC telemetry tests.
28 r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4029)
[email protected]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$",
Sergey Ulanov937d6eb2017-08-28 22:35:38233 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]" +
234 r"remote_test_server_config\.cc$",
lukasza7947ccd2016-07-28 21:56:25235 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54236 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
sergeyu2c41f9842016-12-10 01:45:16237 r"^remoting[\\\/]protocol[\\\/]webrtc_transport\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53238 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
239 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45240 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
241 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
242 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
243 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
244 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49245 ),
[email protected]23e6cbc2012-06-16 18:51:20246 ),
[email protected]52657f62013-05-20 05:30:31247 (
tomhudsone2c14d552016-05-26 17:07:46248 'setMatrixClip',
249 (
250 'Overriding setMatrixClip() is prohibited; ',
251 'the base function is deprecated. ',
252 ),
253 True,
254 (),
255 ),
256 (
[email protected]52657f62013-05-20 05:30:31257 'SkRefPtr',
258 (
259 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22260 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31261 ),
262 True,
263 (),
264 ),
265 (
266 'SkAutoRef',
267 (
268 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22269 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31270 ),
271 True,
272 (),
273 ),
274 (
275 'SkAutoTUnref',
276 (
277 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22278 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31279 ),
280 True,
281 (),
282 ),
283 (
284 'SkAutoUnref',
285 (
286 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
287 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22288 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31289 ),
290 True,
291 (),
292 ),
[email protected]d89eec82013-12-03 14:10:59293 (
294 r'/HANDLE_EINTR\(.*close',
295 (
296 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
297 'descriptor will be closed, and it is incorrect to retry the close.',
298 'Either call close directly and ignore its return value, or wrap close',
299 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
300 ),
301 True,
302 (),
303 ),
304 (
305 r'/IGNORE_EINTR\((?!.*close)',
306 (
307 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
308 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
309 ),
310 True,
311 (
312 # Files that #define IGNORE_EINTR.
313 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
314 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
315 ),
316 ),
[email protected]ec5b3f02014-04-04 18:43:43317 (
318 r'/v8::Extension\(',
319 (
320 'Do not introduce new v8::Extensions into the code base, use',
321 'gin::Wrappable instead. See http://crbug.com/334679',
322 ),
323 True,
[email protected]f55c90ee62014-04-12 00:50:03324 (
joaodasilva718f87672014-08-30 09:25:49325 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03326 ),
[email protected]ec5b3f02014-04-04 18:43:43327 ),
skyostilf9469f72015-04-20 10:38:52328 (
jame2d1a952016-04-02 00:27:10329 '#pragma comment(lib,',
330 (
331 'Specify libraries to link with in build files and not in the source.',
332 ),
333 True,
334 (),
335 ),
fdorayc4ac18d2017-05-01 21:39:59336 (
Kevin Marshall342ddd62017-08-24 17:22:36337 r'/(WebThread|BrowserThread)::(FILE|FILE_USER_BLOCKING|DB|CACHE)',
Gabriel Charette664e4482017-06-13 19:55:29338 (
339 'The non-UI/IO BrowserThreads are deprecated, please migrate this',
340 'code to TaskScheduler. See https://goo.gl/mDSxKl for details.',
341 'For questions, contact base/task_scheduler/OWNERS.',
342 ),
343 True,
344 (),
345 ),
346 (
gabd52c912a2017-05-11 04:15:59347 'base::SequenceChecker',
348 (
349 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
350 ),
351 False,
352 (),
353 ),
354 (
355 'base::ThreadChecker',
356 (
357 'Consider using THREAD_CHECKER macros instead of the class directly.',
358 ),
359 False,
360 (),
361 ),
dbeamb6f4fde2017-06-15 04:03:06362 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06363 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
364 (
365 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
366 'deprecated (http://crbug.com/634507). Please avoid converting away',
367 'from the Time types in Chromium code, especially if any math is',
368 'being done on time values. For interfacing with platform/library',
369 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
370 'type converter methods instead. For faking TimeXXX values (for unit',
371 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
372 'other use cases, please contact base/time/OWNERS.',
373 ),
374 False,
375 (),
376 ),
377 (
dbeamb6f4fde2017-06-15 04:03:06378 'CallJavascriptFunctionUnsafe',
379 (
380 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
381 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
382 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
383 ),
384 False,
385 (
386 r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$',
387 r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$',
388 r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$',
389 ),
390 ),
dskiba1474c2bfd62017-07-20 02:19:24391 (
392 'leveldb::DB::Open',
393 (
394 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
395 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
396 "Chrome's tracing, making their memory usage visible.",
397 ),
398 True,
399 (
400 r'^third_party/leveldatabase/.*\.(cc|h)$',
401 ),
Gabriel Charette0592c3a2017-07-26 12:02:04402 ),
403 (
Gabriel Charetted9839bc2017-07-29 14:17:47404 'MessageLoop::QuitWhenIdleClosure',
Gabriel Charette0592c3a2017-07-26 12:02:04405 (
Robert Liao64b7ab22017-08-04 23:03:43406 'MessageLoop::QuitWhenIdleClosure is deprecated. Please migrate to',
407 'Runloop.',
Gabriel Charette0592c3a2017-07-26 12:02:04408 ),
409 True,
410 (),
Gabriel Charetted9839bc2017-07-29 14:17:47411 ),
412 (
413 'RunLoop::QuitCurrent',
414 (
Robert Liao64b7ab22017-08-04 23:03:43415 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
416 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47417 ),
418 True,
419 (),
Gabriel Charettea44975052017-08-21 23:14:04420 ),
421 (
422 'base::ScopedMockTimeMessageLoopTaskRunner',
423 (
424 'ScopedMockTimeMessageLoopTaskRunner is deprecated.',
425 ),
426 True,
427 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57428 ),
429 (
430 r'std::regex',
431 (
432 'Using std::regex adds unnecessary binary size to Chrome. Please use',
433 're2::RE2 instead (crbug/755321)',
434 ),
435 True,
436 (),
dskiba1474c2bfd62017-07-20 02:19:24437 )
[email protected]127f18ec2012-06-16 05:05:59438)
439
wnwenbdc444e2016-05-25 13:44:15440
mlamouria82272622014-09-16 18:45:04441_IPC_ENUM_TRAITS_DEPRECATED = (
442 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
443 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
444
[email protected]127f18ec2012-06-16 05:05:59445
Sean Kau46e29bc2017-08-28 16:31:16446# These paths contain test data and other known invalid JSON files.
447_KNOWN_INVALID_JSON_FILE_PATTERNS = [
448 r'test[\\\/]data[\\\/]',
449 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
450 r'^third_party[\\\/]protobuf[\\\/]',
451]
452
453
[email protected]b00342e7f2013-03-26 16:21:54454_VALID_OS_MACROS = (
455 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08456 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54457 'OS_ANDROID',
458 'OS_BSD',
459 'OS_CAT', # For testing.
460 'OS_CHROMEOS',
461 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37462 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54463 'OS_IOS',
464 'OS_LINUX',
465 'OS_MACOSX',
466 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21467 'OS_NACL_NONSFI',
468 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12469 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54470 'OS_OPENBSD',
471 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37472 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54473 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54474 'OS_WIN',
475)
476
477
agrievef32bcc72016-04-04 14:57:40478_ANDROID_SPECIFIC_PYDEPS_FILES = [
479 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04480 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58481 'build/secondary/third_party/android_platform/'
482 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19483 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40484]
485
wnwenbdc444e2016-05-25 13:44:15486
agrievef32bcc72016-04-04 14:57:40487_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40488]
489
wnwenbdc444e2016-05-25 13:44:15490
agrievef32bcc72016-04-04 14:57:40491_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
492
493
[email protected]55459852011-08-10 15:17:19494def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
495 """Attempts to prevent use of functions intended only for testing in
496 non-testing code. For now this is just a best-effort implementation
497 that ignores header files and may have some false positives. A
498 better implementation would probably need a proper C++ parser.
499 """
500 # We only scan .cc files and the like, as the declaration of
501 # for-testing functions in header files are hard to distinguish from
502 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44503 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19504
jochenc0d4808c2015-07-27 09:25:42505 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19506 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09507 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19508 exclusion_pattern = input_api.re.compile(
509 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
510 base_function_pattern, base_function_pattern))
511
512 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44513 black_list = (_EXCLUDED_PATHS +
514 _TEST_CODE_EXCLUDED_PATHS +
515 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19516 return input_api.FilterSourceFile(
517 affected_file,
518 white_list=(file_inclusion_pattern, ),
519 black_list=black_list)
520
521 problems = []
522 for f in input_api.AffectedSourceFiles(FilterFile):
523 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24524 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03525 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46526 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03527 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19528 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03529 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19530
531 if problems:
[email protected]f7051d52013-04-02 18:31:42532 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03533 else:
534 return []
[email protected]55459852011-08-10 15:17:19535
536
[email protected]10689ca2011-09-02 02:31:54537def _CheckNoIOStreamInHeaders(input_api, output_api):
538 """Checks to make sure no .h files include <iostream>."""
539 files = []
540 pattern = input_api.re.compile(r'^#include\s*<iostream>',
541 input_api.re.MULTILINE)
542 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
543 if not f.LocalPath().endswith('.h'):
544 continue
545 contents = input_api.ReadFile(f)
546 if pattern.search(contents):
547 files.append(f)
548
549 if len(files):
yolandyandaabc6d2016-04-18 18:29:39550 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06551 'Do not #include <iostream> in header files, since it inserts static '
552 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54553 '#include <ostream>. See http://crbug.com/94794',
554 files) ]
555 return []
556
557
[email protected]72df4e782012-06-21 16:28:18558def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52559 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18560 problems = []
561 for f in input_api.AffectedFiles():
562 if (not f.LocalPath().endswith(('.cc', '.mm'))):
563 continue
564
565 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04566 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18567 problems.append(' %s:%d' % (f.LocalPath(), line_num))
568
569 if not problems:
570 return []
571 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
572 '\n'.join(problems))]
573
574
danakj61c1aa22015-10-26 19:55:52575def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57576 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52577 errors = []
578 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
579 input_api.re.MULTILINE)
580 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
581 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
582 continue
583 for lnum, line in f.ChangedContents():
584 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17585 errors.append(output_api.PresubmitError(
586 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57587 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17588 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52589 return errors
590
591
mcasasb7440c282015-02-04 14:52:19592def _FindHistogramNameInLine(histogram_name, line):
593 """Tries to find a histogram name or prefix in a line."""
594 if not "affected-histogram" in line:
595 return histogram_name in line
596 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
597 # the histogram_name.
598 if not '"' in line:
599 return False
600 histogram_prefix = line.split('\"')[1]
601 return histogram_prefix in histogram_name
602
603
604def _CheckUmaHistogramChanges(input_api, output_api):
605 """Check that UMA histogram names in touched lines can still be found in other
606 lines of the patch or in histograms.xml. Note that this check would not catch
607 the reverse: changes in histograms.xml not matched in the code itself."""
608 touched_histograms = []
609 histograms_xml_modifications = []
610 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
611 for f in input_api.AffectedFiles():
612 # If histograms.xml itself is modified, keep the modified lines for later.
613 if f.LocalPath().endswith(('histograms.xml')):
614 histograms_xml_modifications = f.ChangedContents()
615 continue
616 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
617 continue
618 for line_num, line in f.ChangedContents():
619 found = pattern.search(line)
620 if found:
621 touched_histograms.append([found.group(1), f, line_num])
622
623 # Search for the touched histogram names in the local modifications to
624 # histograms.xml, and, if not found, on the base histograms.xml file.
625 unmatched_histograms = []
626 for histogram_info in touched_histograms:
627 histogram_name_found = False
628 for line_num, line in histograms_xml_modifications:
629 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
630 if histogram_name_found:
631 break
632 if not histogram_name_found:
633 unmatched_histograms.append(histogram_info)
634
eromanb90c82e7e32015-04-01 15:13:49635 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19636 problems = []
637 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49638 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19639 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45640 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19641 histogram_name_found = False
642 for line in histograms_xml:
643 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
644 if histogram_name_found:
645 break
646 if not histogram_name_found:
647 problems.append(' [%s:%d] %s' %
648 (f.LocalPath(), line_num, histogram_name))
649
650 if not problems:
651 return []
652 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
653 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49654 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19655
wnwenbdc444e2016-05-25 13:44:15656
yolandyandaabc6d2016-04-18 18:29:39657def _CheckFlakyTestUsage(input_api, output_api):
658 """Check that FlakyTest annotation is our own instead of the android one"""
659 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
660 files = []
661 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
662 if f.LocalPath().endswith('Test.java'):
663 if pattern.search(input_api.ReadFile(f)):
664 files.append(f)
665 if len(files):
666 return [output_api.PresubmitError(
667 'Use org.chromium.base.test.util.FlakyTest instead of '
668 'android.test.FlakyTest',
669 files)]
670 return []
mcasasb7440c282015-02-04 14:52:19671
wnwenbdc444e2016-05-25 13:44:15672
[email protected]8ea5d4b2011-09-13 21:49:22673def _CheckNoNewWStrings(input_api, output_api):
674 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27675 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22676 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20677 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57678 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34679 '/win/' in f.LocalPath() or
680 'chrome_elf' in f.LocalPath() or
681 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20682 continue
[email protected]8ea5d4b2011-09-13 21:49:22683
[email protected]a11dbe9b2012-08-07 01:32:58684 allowWString = False
[email protected]b5c24292011-11-28 14:38:20685 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58686 if 'presubmit: allow wstring' in line:
687 allowWString = True
688 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27689 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58690 allowWString = False
691 else:
692 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22693
[email protected]55463aa62011-10-12 00:48:27694 if not problems:
695 return []
696 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58697 ' If you are calling a cross-platform API that accepts a wstring, '
698 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27699 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22700
701
[email protected]2a8ac9c2011-10-19 17:20:44702def _CheckNoDEPSGIT(input_api, output_api):
703 """Make sure .DEPS.git is never modified manually."""
704 if any(f.LocalPath().endswith('.DEPS.git') for f in
705 input_api.AffectedFiles()):
706 return [output_api.PresubmitError(
707 'Never commit changes to .DEPS.git. This file is maintained by an\n'
708 'automated system based on what\'s in DEPS and your changes will be\n'
709 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34710 '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:44711 'for more information')]
712 return []
713
714
tandriief664692014-09-23 14:51:47715def _CheckValidHostsInDEPS(input_api, output_api):
716 """Checks that DEPS file deps are from allowed_hosts."""
717 # Run only if DEPS file has been modified to annoy fewer bystanders.
718 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
719 return []
720 # Outsource work to gclient verify
721 try:
722 input_api.subprocess.check_output(['gclient', 'verify'])
723 return []
724 except input_api.subprocess.CalledProcessError, error:
725 return [output_api.PresubmitError(
726 'DEPS file must have only git dependencies.',
727 long_text=error.output)]
728
729
[email protected]127f18ec2012-06-16 05:05:59730def _CheckNoBannedFunctions(input_api, output_api):
731 """Make sure that banned functions are not used."""
732 warnings = []
733 errors = []
734
wnwenbdc444e2016-05-25 13:44:15735 def IsBlacklisted(affected_file, blacklist):
736 local_path = affected_file.LocalPath()
737 for item in blacklist:
738 if input_api.re.match(item, local_path):
739 return True
740 return False
741
742 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
743 matched = False
744 if func_name[0:1] == '/':
745 regex = func_name[1:]
746 if input_api.re.search(regex, line):
747 matched = True
748 elif func_name in line:
dchenge07de812016-06-20 19:27:17749 matched = True
wnwenbdc444e2016-05-25 13:44:15750 if matched:
dchenge07de812016-06-20 19:27:17751 problems = warnings
wnwenbdc444e2016-05-25 13:44:15752 if error:
dchenge07de812016-06-20 19:27:17753 problems = errors
wnwenbdc444e2016-05-25 13:44:15754 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
755 for message_line in message:
756 problems.append(' %s' % message_line)
757
[email protected]127f18ec2012-06-16 05:05:59758 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
759 for f in input_api.AffectedFiles(file_filter=file_filter):
760 for line_num, line in f.ChangedContents():
761 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15762 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59763
764 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
765 for f in input_api.AffectedFiles(file_filter=file_filter):
766 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49767 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49768 if IsBlacklisted(f, excluded_paths):
769 continue
wnwenbdc444e2016-05-25 13:44:15770 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59771
772 result = []
773 if (warnings):
774 result.append(output_api.PresubmitPromptWarning(
775 'Banned functions were used.\n' + '\n'.join(warnings)))
776 if (errors):
777 result.append(output_api.PresubmitError(
778 'Banned functions were used.\n' + '\n'.join(errors)))
779 return result
780
781
[email protected]6c063c62012-07-11 19:11:06782def _CheckNoPragmaOnce(input_api, output_api):
783 """Make sure that banned functions are not used."""
784 files = []
785 pattern = input_api.re.compile(r'^#pragma\s+once',
786 input_api.re.MULTILINE)
787 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
788 if not f.LocalPath().endswith('.h'):
789 continue
790 contents = input_api.ReadFile(f)
791 if pattern.search(contents):
792 files.append(f)
793
794 if files:
795 return [output_api.PresubmitError(
796 'Do not use #pragma once in header files.\n'
797 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
798 files)]
799 return []
800
[email protected]127f18ec2012-06-16 05:05:59801
[email protected]e7479052012-09-19 00:26:12802def _CheckNoTrinaryTrueFalse(input_api, output_api):
803 """Checks to make sure we don't introduce use of foo ? true : false."""
804 problems = []
805 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
806 for f in input_api.AffectedFiles():
807 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
808 continue
809
810 for line_num, line in f.ChangedContents():
811 if pattern.match(line):
812 problems.append(' %s:%d' % (f.LocalPath(), line_num))
813
814 if not problems:
815 return []
816 return [output_api.PresubmitPromptWarning(
817 'Please consider avoiding the "? true : false" pattern if possible.\n' +
818 '\n'.join(problems))]
819
820
[email protected]55f9f382012-07-31 11:02:18821def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28822 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18823 change. Breaking - rules is an error, breaking ! rules is a
824 warning.
825 """
mohan.reddyf21db962014-10-16 12:26:47826 import sys
[email protected]55f9f382012-07-31 11:02:18827 # We need to wait until we have an input_api object and use this
828 # roundabout construct to import checkdeps because this file is
829 # eval-ed and thus doesn't have __file__.
830 original_sys_path = sys.path
831 try:
832 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47833 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18834 import checkdeps
835 from cpp_checker import CppChecker
rhalavati08acd232017-04-03 07:23:28836 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18837 from rules import Rule
838 finally:
839 # Restore sys.path to what it was before.
840 sys.path = original_sys_path
841
842 added_includes = []
rhalavati08acd232017-04-03 07:23:28843 added_imports = []
[email protected]55f9f382012-07-31 11:02:18844 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28845 if CppChecker.IsCppFile(f.LocalPath()):
846 changed_lines = [line for line_num, line in f.ChangedContents()]
847 added_includes.append([f.LocalPath(), changed_lines])
848 elif ProtoChecker.IsProtoFile(f.LocalPath()):
849 changed_lines = [line for line_num, line in f.ChangedContents()]
850 added_imports.append([f.LocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18851
[email protected]26385172013-05-09 23:11:35852 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18853
854 error_descriptions = []
855 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28856 error_subjects = set()
857 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18858 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
859 added_includes):
860 description_with_path = '%s\n %s' % (path, rule_description)
861 if rule_type == Rule.DISALLOW:
862 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28863 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18864 else:
865 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28866 warning_subjects.add("#includes")
867
868 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
869 added_imports):
870 description_with_path = '%s\n %s' % (path, rule_description)
871 if rule_type == Rule.DISALLOW:
872 error_descriptions.append(description_with_path)
873 error_subjects.add("imports")
874 else:
875 warning_descriptions.append(description_with_path)
876 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18877
878 results = []
879 if error_descriptions:
880 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28881 'You added one or more %s that violate checkdeps rules.'
882 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18883 error_descriptions))
884 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42885 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28886 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18887 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28888 '%s? See relevant DEPS file(s) for details and contacts.' %
889 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18890 warning_descriptions))
891 return results
892
893
[email protected]fbcafe5a2012-08-08 15:31:22894def _CheckFilePermissions(input_api, output_api):
895 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15896 if input_api.platform == 'win32':
897 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29898 checkperms_tool = input_api.os_path.join(
899 input_api.PresubmitLocalPath(),
900 'tools', 'checkperms', 'checkperms.py')
901 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47902 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22903 for f in input_api.AffectedFiles():
904 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11905 try:
906 input_api.subprocess.check_output(args)
907 return []
908 except input_api.subprocess.CalledProcessError as error:
909 return [output_api.PresubmitError(
910 'checkperms.py failed:',
911 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22912
913
robertocn832f5992017-01-04 19:01:30914def _CheckTeamTags(input_api, output_api):
915 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
916 checkteamtags_tool = input_api.os_path.join(
917 input_api.PresubmitLocalPath(),
918 'tools', 'checkteamtags', 'checkteamtags.py')
919 args = [input_api.python_executable, checkteamtags_tool,
920 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22921 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30922 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
923 'OWNERS']
924 try:
925 if files:
926 input_api.subprocess.check_output(args + files)
927 return []
928 except input_api.subprocess.CalledProcessError as error:
929 return [output_api.PresubmitError(
930 'checkteamtags.py failed:',
931 long_text=error.output)]
932
933
[email protected]c8278b32012-10-30 20:35:49934def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
935 """Makes sure we don't include ui/aura/window_property.h
936 in header files.
937 """
938 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
939 errors = []
940 for f in input_api.AffectedFiles():
941 if not f.LocalPath().endswith('.h'):
942 continue
943 for line_num, line in f.ChangedContents():
944 if pattern.match(line):
945 errors.append(' %s:%d' % (f.LocalPath(), line_num))
946
947 results = []
948 if errors:
949 results.append(output_api.PresubmitError(
950 'Header files should not include ui/aura/window_property.h', errors))
951 return results
952
953
[email protected]70ca77752012-11-20 03:45:03954def _CheckForVersionControlConflictsInFile(input_api, f):
955 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
956 errors = []
957 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23958 if f.LocalPath().endswith('.md'):
959 # First-level headers in markdown look a lot like version control
960 # conflict markers. http://daringfireball.net/projects/markdown/basics
961 continue
[email protected]70ca77752012-11-20 03:45:03962 if pattern.match(line):
963 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
964 return errors
965
966
967def _CheckForVersionControlConflicts(input_api, output_api):
968 """Usually this is not intentional and will cause a compile failure."""
969 errors = []
970 for f in input_api.AffectedFiles():
971 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
972
973 results = []
974 if errors:
975 results.append(output_api.PresubmitError(
976 'Version control conflict markers found, please resolve.', errors))
977 return results
978
estadee17314a02017-01-12 16:22:16979def _CheckGoogleSupportAnswerUrl(input_api, output_api):
980 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
981 errors = []
982 for f in input_api.AffectedFiles():
983 for line_num, line in f.ChangedContents():
984 if pattern.search(line):
985 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
986
987 results = []
988 if errors:
989 results.append(output_api.PresubmitPromptWarning(
990 'Found Google support URL addressed by answer number. Please replace with '
991 'a p= identifier instead. See crbug.com/679462\n', errors))
992 return results
993
[email protected]70ca77752012-11-20 03:45:03994
[email protected]06e6d0ff2012-12-11 01:36:44995def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
996 def FilterFile(affected_file):
997 """Filter function for use with input_api.AffectedSourceFiles,
998 below. This filters out everything except non-test files from
999 top-level directories that generally speaking should not hard-code
1000 service URLs (e.g. src/android_webview/, src/content/ and others).
1001 """
1002 return input_api.FilterSourceFile(
1003 affected_file,
[email protected]78bb39d62012-12-11 15:11:561004 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441005 black_list=(_EXCLUDED_PATHS +
1006 _TEST_CODE_EXCLUDED_PATHS +
1007 input_api.DEFAULT_BLACK_LIST))
1008
reillyi38965732015-11-16 18:27:331009 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1010 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461011 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1012 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441013 problems = [] # items are (filename, line_number, line)
1014 for f in input_api.AffectedSourceFiles(FilterFile):
1015 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461016 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441017 problems.append((f.LocalPath(), line_num, line))
1018
1019 if problems:
[email protected]f7051d52013-04-02 18:31:421020 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441021 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581022 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441023 [' %s:%d: %s' % (
1024 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031025 else:
1026 return []
[email protected]06e6d0ff2012-12-11 01:36:441027
1028
[email protected]d2530012013-01-25 16:39:271029def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1030 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311031 The native_client_sdk directory is excluded because it has auto-generated PNG
1032 files for documentation.
[email protected]d2530012013-01-25 16:39:271033 """
[email protected]d2530012013-01-25 16:39:271034 errors = []
binji0dcdf342014-12-12 18:32:311035 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1036 black_list = (r'^native_client_sdk[\\\/]',)
1037 file_filter = lambda f: input_api.FilterSourceFile(
1038 f, white_list=white_list, black_list=black_list)
1039 for f in input_api.AffectedFiles(include_deletes=False,
1040 file_filter=file_filter):
1041 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271042
1043 results = []
1044 if errors:
1045 results.append(output_api.PresubmitError(
1046 'The name of PNG files should not have abbreviations. \n'
1047 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1048 'Contact [email protected] if you have questions.', errors))
1049 return results
1050
1051
Daniel Cheng4dcdb6b2017-04-13 08:30:171052def _ExtractAddRulesFromParsedDeps(parsed_deps):
1053 """Extract the rules that add dependencies from a parsed DEPS file.
1054
1055 Args:
1056 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1057 add_rules = set()
1058 add_rules.update([
1059 rule[1:] for rule in parsed_deps.get('include_rules', [])
1060 if rule.startswith('+') or rule.startswith('!')
1061 ])
1062 for specific_file, rules in parsed_deps.get('specific_include_rules',
1063 {}).iteritems():
1064 add_rules.update([
1065 rule[1:] for rule in rules
1066 if rule.startswith('+') or rule.startswith('!')
1067 ])
1068 return add_rules
1069
1070
1071def _ParseDeps(contents):
1072 """Simple helper for parsing DEPS files."""
1073 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171074 class _VarImpl:
1075
1076 def __init__(self, local_scope):
1077 self._local_scope = local_scope
1078
1079 def Lookup(self, var_name):
1080 """Implements the Var syntax."""
1081 try:
1082 return self._local_scope['vars'][var_name]
1083 except KeyError:
1084 raise Exception('Var is not defined: %s' % var_name)
1085
1086 local_scope = {}
1087 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171088 'Var': _VarImpl(local_scope).Lookup,
1089 }
1090 exec contents in global_scope, local_scope
1091 return local_scope
1092
1093
1094def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081095 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411096 a set of DEPS entries that we should look up.
1097
1098 For a directory (rather than a specific filename) we fake a path to
1099 a specific filename by adding /DEPS. This is chosen as a file that
1100 will seldom or never be subject to per-file include_rules.
1101 """
[email protected]2b438d62013-11-14 17:54:141102 # We ignore deps entries on auto-generated directories.
1103 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081104
Daniel Cheng4dcdb6b2017-04-13 08:30:171105 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1106 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1107
1108 added_deps = new_deps.difference(old_deps)
1109
[email protected]2b438d62013-11-14 17:54:141110 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171111 for added_dep in added_deps:
1112 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1113 continue
1114 # Assume that a rule that ends in .h is a rule for a specific file.
1115 if added_dep.endswith('.h'):
1116 results.add(added_dep)
1117 else:
1118 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081119 return results
1120
1121
[email protected]e871964c2013-05-13 14:14:551122def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1123 """When a dependency prefixed with + is added to a DEPS file, we
1124 want to make sure that the change is reviewed by an OWNER of the
1125 target file or directory, to avoid layering violations from being
1126 introduced. This check verifies that this happens.
1127 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171128 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241129
1130 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191131 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241132 for f in input_api.AffectedFiles(include_deletes=False,
1133 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551134 filename = input_api.os_path.basename(f.LocalPath())
1135 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171136 virtual_depended_on_files.update(_CalculateAddedDeps(
1137 input_api.os_path,
1138 '\n'.join(f.OldContents()),
1139 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551140
[email protected]e871964c2013-05-13 14:14:551141 if not virtual_depended_on_files:
1142 return []
1143
1144 if input_api.is_committing:
1145 if input_api.tbr:
1146 return [output_api.PresubmitNotifyResult(
1147 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271148 if input_api.dry_run:
1149 return [output_api.PresubmitNotifyResult(
1150 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551151 if not input_api.change.issue:
1152 return [output_api.PresubmitError(
1153 "DEPS approval by OWNERS check failed: this change has "
1154 "no Rietveld issue number, so we can't check it for approvals.")]
1155 output = output_api.PresubmitError
1156 else:
1157 output = output_api.PresubmitNotifyResult
1158
1159 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501160 owner_email, reviewers = (
1161 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1162 input_api,
1163 owners_db.email_regexp,
1164 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551165
1166 owner_email = owner_email or input_api.change.author_email
1167
[email protected]de4f7d22013-05-23 14:27:461168 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511169 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461170 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551171 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1172 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411173
1174 # We strip the /DEPS part that was added by
1175 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1176 # directory.
1177 def StripDeps(path):
1178 start_deps = path.rfind('/DEPS')
1179 if start_deps != -1:
1180 return path[:start_deps]
1181 else:
1182 return path
1183 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551184 for path in missing_files]
1185
1186 if unapproved_dependencies:
1187 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151188 output('You need LGTM from owners of depends-on paths in DEPS that were '
1189 'modified in this CL:\n %s' %
1190 '\n '.join(sorted(unapproved_dependencies)))]
1191 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1192 output_list.append(output(
1193 'Suggested missing target path OWNERS:\n %s' %
1194 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551195 return output_list
1196
1197 return []
1198
1199
[email protected]85218562013-11-22 07:41:401200def _CheckSpamLogging(input_api, output_api):
1201 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1202 black_list = (_EXCLUDED_PATHS +
1203 _TEST_CODE_EXCLUDED_PATHS +
1204 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501205 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191206 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481207 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461208 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121209 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1210 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581211 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591212 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161213 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031214 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151215 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1216 r"^chromecast[\\\/]",
1217 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481218 r"^components[\\\/]browser_watcher[\\\/]"
1219 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311220 r"^components[\\\/]html_viewer[\\\/]"
1221 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461222 # TODO(peter): Remove this exception. https://crbug.com/534537
1223 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1224 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251225 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1226 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241227 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111228 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151229 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111230 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521231 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501232 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361233 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311234 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131235 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001236 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441237 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451238 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021239 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351240 r"dump_file_system.cc$",
1241 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401242 source_file_filter = lambda x: input_api.FilterSourceFile(
1243 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1244
thomasanderson625d3932017-03-29 07:16:581245 log_info = set([])
1246 printf = set([])
[email protected]85218562013-11-22 07:41:401247
1248 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581249 for _, line in f.ChangedContents():
1250 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1251 log_info.add(f.LocalPath())
1252 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1253 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371254
thomasanderson625d3932017-03-29 07:16:581255 if input_api.re.search(r"\bprintf\(", line):
1256 printf.add(f.LocalPath())
1257 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1258 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401259
1260 if log_info:
1261 return [output_api.PresubmitError(
1262 'These files spam the console log with LOG(INFO):',
1263 items=log_info)]
1264 if printf:
1265 return [output_api.PresubmitError(
1266 'These files spam the console log with printf/fprintf:',
1267 items=printf)]
1268 return []
1269
1270
[email protected]49aa76a2013-12-04 06:59:161271def _CheckForAnonymousVariables(input_api, output_api):
1272 """These types are all expected to hold locks while in scope and
1273 so should never be anonymous (which causes them to be immediately
1274 destroyed)."""
1275 they_who_must_be_named = [
1276 'base::AutoLock',
1277 'base::AutoReset',
1278 'base::AutoUnlock',
1279 'SkAutoAlphaRestore',
1280 'SkAutoBitmapShaderInstall',
1281 'SkAutoBlitterChoose',
1282 'SkAutoBounderCommit',
1283 'SkAutoCallProc',
1284 'SkAutoCanvasRestore',
1285 'SkAutoCommentBlock',
1286 'SkAutoDescriptor',
1287 'SkAutoDisableDirectionCheck',
1288 'SkAutoDisableOvalCheck',
1289 'SkAutoFree',
1290 'SkAutoGlyphCache',
1291 'SkAutoHDC',
1292 'SkAutoLockColors',
1293 'SkAutoLockPixels',
1294 'SkAutoMalloc',
1295 'SkAutoMaskFreeImage',
1296 'SkAutoMutexAcquire',
1297 'SkAutoPathBoundsUpdate',
1298 'SkAutoPDFRelease',
1299 'SkAutoRasterClipValidate',
1300 'SkAutoRef',
1301 'SkAutoTime',
1302 'SkAutoTrace',
1303 'SkAutoUnref',
1304 ]
1305 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1306 # bad: base::AutoLock(lock.get());
1307 # not bad: base::AutoLock lock(lock.get());
1308 bad_pattern = input_api.re.compile(anonymous)
1309 # good: new base::AutoLock(lock.get())
1310 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1311 errors = []
1312
1313 for f in input_api.AffectedFiles():
1314 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1315 continue
1316 for linenum, line in f.ChangedContents():
1317 if bad_pattern.search(line) and not good_pattern.search(line):
1318 errors.append('%s:%d' % (f.LocalPath(), linenum))
1319
1320 if errors:
1321 return [output_api.PresubmitError(
1322 'These lines create anonymous variables that need to be named:',
1323 items=errors)]
1324 return []
1325
1326
[email protected]999261d2014-03-03 20:08:081327def _CheckUserActionUpdate(input_api, output_api):
1328 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521329 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081330 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521331 # If actions.xml is already included in the changelist, the PRESUBMIT
1332 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081333 return []
1334
[email protected]999261d2014-03-03 20:08:081335 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1336 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521337 current_actions = None
[email protected]999261d2014-03-03 20:08:081338 for f in input_api.AffectedFiles(file_filter=file_filter):
1339 for line_num, line in f.ChangedContents():
1340 match = input_api.re.search(action_re, line)
1341 if match:
[email protected]2f92dec2014-03-07 19:21:521342 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1343 # loaded only once.
1344 if not current_actions:
1345 with open('tools/metrics/actions/actions.xml') as actions_f:
1346 current_actions = actions_f.read()
1347 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081348 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521349 action = 'name="{0}"'.format(action_name)
1350 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081351 return [output_api.PresubmitPromptWarning(
1352 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521353 'tools/metrics/actions/actions.xml. Please run '
1354 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081355 % (f.LocalPath(), line_num, action_name))]
1356 return []
1357
1358
Daniel Cheng13ca61a882017-08-25 15:11:251359def _ImportJSONCommentEater(input_api):
1360 import sys
1361 sys.path = sys.path + [input_api.os_path.join(
1362 input_api.PresubmitLocalPath(),
1363 'tools', 'json_comment_eater')]
1364 import json_comment_eater
1365 return json_comment_eater
1366
1367
[email protected]99171a92014-06-03 08:44:471368def _GetJSONParseError(input_api, filename, eat_comments=True):
1369 try:
1370 contents = input_api.ReadFile(filename)
1371 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251372 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131373 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471374
1375 input_api.json.loads(contents)
1376 except ValueError as e:
1377 return e
1378 return None
1379
1380
1381def _GetIDLParseError(input_api, filename):
1382 try:
1383 contents = input_api.ReadFile(filename)
1384 idl_schema = input_api.os_path.join(
1385 input_api.PresubmitLocalPath(),
1386 'tools', 'json_schema_compiler', 'idl_schema.py')
1387 process = input_api.subprocess.Popen(
1388 [input_api.python_executable, idl_schema],
1389 stdin=input_api.subprocess.PIPE,
1390 stdout=input_api.subprocess.PIPE,
1391 stderr=input_api.subprocess.PIPE,
1392 universal_newlines=True)
1393 (_, error) = process.communicate(input=contents)
1394 return error or None
1395 except ValueError as e:
1396 return e
1397
1398
1399def _CheckParseErrors(input_api, output_api):
1400 """Check that IDL and JSON files do not contain syntax errors."""
1401 actions = {
1402 '.idl': _GetIDLParseError,
1403 '.json': _GetJSONParseError,
1404 }
[email protected]99171a92014-06-03 08:44:471405 # Most JSON files are preprocessed and support comments, but these do not.
1406 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491407 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471408 ]
1409 # Only run IDL checker on files in these directories.
1410 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491411 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1412 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471413 ]
1414
1415 def get_action(affected_file):
1416 filename = affected_file.LocalPath()
1417 return actions.get(input_api.os_path.splitext(filename)[1])
1418
[email protected]99171a92014-06-03 08:44:471419 def FilterFile(affected_file):
1420 action = get_action(affected_file)
1421 if not action:
1422 return False
1423 path = affected_file.LocalPath()
1424
Sean Kau46e29bc2017-08-28 16:31:161425 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471426 return False
1427
1428 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161429 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471430 return False
1431 return True
1432
1433 results = []
1434 for affected_file in input_api.AffectedFiles(
1435 file_filter=FilterFile, include_deletes=False):
1436 action = get_action(affected_file)
1437 kwargs = {}
1438 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161439 _MatchesFile(input_api, json_no_comments_patterns,
1440 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471441 kwargs['eat_comments'] = False
1442 parse_error = action(input_api,
1443 affected_file.AbsoluteLocalPath(),
1444 **kwargs)
1445 if parse_error:
1446 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1447 (affected_file.LocalPath(), parse_error)))
1448 return results
1449
1450
[email protected]760deea2013-12-10 19:33:491451def _CheckJavaStyle(input_api, output_api):
1452 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471453 import sys
[email protected]760deea2013-12-10 19:33:491454 original_sys_path = sys.path
1455 try:
1456 sys.path = sys.path + [input_api.os_path.join(
1457 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1458 import checkstyle
1459 finally:
1460 # Restore sys.path to what it was before.
1461 sys.path = original_sys_path
1462
1463 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091464 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511465 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491466
1467
Sean Kau46e29bc2017-08-28 16:31:161468def _MatchesFile(input_api, patterns, path):
1469 for pattern in patterns:
1470 if input_api.re.search(pattern, path):
1471 return True
1472 return False
1473
1474
dchenge07de812016-06-20 19:27:171475def _CheckIpcOwners(input_api, output_api):
1476 """Checks that affected files involving IPC have an IPC OWNERS rule.
1477
1478 Whether or not a file affects IPC is determined by a simple whitelist of
1479 filename patterns."""
1480 file_patterns = [
palmerb19a0932017-01-24 04:00:311481 # Legacy IPC:
dchenge07de812016-06-20 19:27:171482 '*_messages.cc',
1483 '*_messages*.h',
1484 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311485 # Mojo IPC:
dchenge07de812016-06-20 19:27:171486 '*.mojom',
1487 '*_struct_traits*.*',
1488 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311489 '*.typemap',
1490 # Android native IPC:
1491 '*.aidl',
1492 # Blink uses a different file naming convention:
1493 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171494 '*StructTraits*.*',
1495 '*TypeConverter*.*',
1496 ]
1497
scottmg7a6ed5ba2016-11-04 18:22:041498 # These third_party directories do not contain IPCs, but contain files
1499 # matching the above patterns, which trigger false positives.
1500 exclude_paths = [
1501 'third_party/crashpad/*',
Nico Weberee3dc9b2017-08-31 17:09:291502 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:041503 ]
1504
dchenge07de812016-06-20 19:27:171505 # Dictionary mapping an OWNERS file path to Patterns.
1506 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1507 # rules ) to a PatternEntry.
1508 # PatternEntry is a dictionary with two keys:
1509 # - 'files': the files that are matched by this pattern
1510 # - 'rules': the per-file rules needed for this pattern
1511 # For example, if we expect OWNERS file to contain rules for *.mojom and
1512 # *_struct_traits*.*, Patterns might look like this:
1513 # {
1514 # '*.mojom': {
1515 # 'files': ...,
1516 # 'rules': [
1517 # 'per-file *.mojom=set noparent',
1518 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1519 # ],
1520 # },
1521 # '*_struct_traits*.*': {
1522 # 'files': ...,
1523 # 'rules': [
1524 # 'per-file *_struct_traits*.*=set noparent',
1525 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1526 # ],
1527 # },
1528 # }
1529 to_check = {}
1530
Daniel Cheng13ca61a882017-08-25 15:11:251531 def AddPatternToCheck(input_file, pattern):
1532 owners_file = input_api.os_path.join(
1533 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1534 if owners_file not in to_check:
1535 to_check[owners_file] = {}
1536 if pattern not in to_check[owners_file]:
1537 to_check[owners_file][pattern] = {
1538 'files': [],
1539 'rules': [
1540 'per-file %s=set noparent' % pattern,
1541 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1542 ]
1543 }
1544 to_check[owners_file][pattern]['files'].append(f)
1545
dchenge07de812016-06-20 19:27:171546 # Iterate through the affected files to see what we actually need to check
1547 # for. We should only nag patch authors about per-file rules if a file in that
1548 # directory would match that pattern. If a directory only contains *.mojom
1549 # files and no *_messages*.h files, we should only nag about rules for
1550 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251551 for f in input_api.AffectedFiles(include_deletes=False):
1552 # Manifest files don't have a strong naming convention. Instead, scan
1553 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161554 if (f.LocalPath().endswith('.json') and
1555 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1556 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251557 json_comment_eater = _ImportJSONCommentEater(input_api)
1558 mostly_json_lines = '\n'.join(f.NewContents())
1559 # Comments aren't allowed in strict JSON, so filter them out.
1560 json_lines = json_comment_eater.Nom(mostly_json_lines)
1561 json_content = input_api.json.loads(json_lines)
1562 if 'interface_provider_specs' in json_content:
1563 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171564 for pattern in file_patterns:
1565 if input_api.fnmatch.fnmatch(
1566 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041567 skip = False
1568 for exclude in exclude_paths:
1569 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1570 skip = True
1571 break
1572 if skip:
1573 continue
Daniel Cheng13ca61a882017-08-25 15:11:251574 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171575 break
1576
1577 # Now go through the OWNERS files we collected, filtering out rules that are
1578 # already present in that OWNERS file.
1579 for owners_file, patterns in to_check.iteritems():
1580 try:
1581 with file(owners_file) as f:
1582 lines = set(f.read().splitlines())
1583 for entry in patterns.itervalues():
1584 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1585 ]
1586 except IOError:
1587 # No OWNERS file, so all the rules are definitely missing.
1588 continue
1589
1590 # All the remaining lines weren't found in OWNERS files, so emit an error.
1591 errors = []
1592 for owners_file, patterns in to_check.iteritems():
1593 missing_lines = []
1594 files = []
1595 for pattern, entry in patterns.iteritems():
1596 missing_lines.extend(entry['rules'])
1597 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1598 if missing_lines:
1599 errors.append(
Daniel Cheng52111692017-06-14 08:00:591600 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171601 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1602
1603 results = []
1604 if errors:
vabrf5ce3bf92016-07-11 14:52:411605 if input_api.is_committing:
1606 output = output_api.PresubmitError
1607 else:
1608 output = output_api.PresubmitPromptWarning
1609 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591610 'Found OWNERS files that need to be updated for IPC security ' +
1611 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171612 long_text='\n\n'.join(errors)))
1613
1614 return results
1615
1616
jbriance9e12f162016-11-25 07:57:501617def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311618 """Checks that added or removed lines in non third party affected
1619 header files do not lead to new useless class or struct forward
1620 declaration.
jbriance9e12f162016-11-25 07:57:501621 """
1622 results = []
1623 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1624 input_api.re.MULTILINE)
1625 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1626 input_api.re.MULTILINE)
1627 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311628 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191629 not f.LocalPath().startswith('third_party/blink') and
1630 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311631 not f.LocalPath().startswith('third_party/WebKit') and
1632 not f.LocalPath().startswith('third_party\\WebKit')):
1633 continue
1634
jbriance9e12f162016-11-25 07:57:501635 if not f.LocalPath().endswith('.h'):
1636 continue
1637
1638 contents = input_api.ReadFile(f)
1639 fwd_decls = input_api.re.findall(class_pattern, contents)
1640 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1641
1642 useless_fwd_decls = []
1643 for decl in fwd_decls:
1644 count = sum(1 for _ in input_api.re.finditer(
1645 r'\b%s\b' % input_api.re.escape(decl), contents))
1646 if count == 1:
1647 useless_fwd_decls.append(decl)
1648
1649 if not useless_fwd_decls:
1650 continue
1651
1652 for line in f.GenerateScmDiff().splitlines():
1653 if (line.startswith('-') and not line.startswith('--') or
1654 line.startswith('+') and not line.startswith('++')):
1655 for decl in useless_fwd_decls:
1656 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1657 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241658 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501659 (f.LocalPath(), decl)))
1660 useless_fwd_decls.remove(decl)
1661
1662 return results
1663
1664
dskiba88634f4e2015-08-14 23:03:291665def _CheckAndroidToastUsage(input_api, output_api):
1666 """Checks that code uses org.chromium.ui.widget.Toast instead of
1667 android.widget.Toast (Chromium Toast doesn't force hardware
1668 acceleration on low-end devices, saving memory).
1669 """
1670 toast_import_pattern = input_api.re.compile(
1671 r'^import android\.widget\.Toast;$')
1672
1673 errors = []
1674
1675 sources = lambda affected_file: input_api.FilterSourceFile(
1676 affected_file,
1677 black_list=(_EXCLUDED_PATHS +
1678 _TEST_CODE_EXCLUDED_PATHS +
1679 input_api.DEFAULT_BLACK_LIST +
1680 (r'^chromecast[\\\/].*',
1681 r'^remoting[\\\/].*')),
1682 white_list=(r'.*\.java$',))
1683
1684 for f in input_api.AffectedSourceFiles(sources):
1685 for line_num, line in f.ChangedContents():
1686 if toast_import_pattern.search(line):
1687 errors.append("%s:%d" % (f.LocalPath(), line_num))
1688
1689 results = []
1690
1691 if errors:
1692 results.append(output_api.PresubmitError(
1693 'android.widget.Toast usage is detected. Android toasts use hardware'
1694 ' acceleration, and can be\ncostly on low-end devices. Please use'
1695 ' org.chromium.ui.widget.Toast instead.\n'
1696 'Contact [email protected] if you have any questions.',
1697 errors))
1698
1699 return results
1700
1701
dgnaa68d5e2015-06-10 10:08:221702def _CheckAndroidCrLogUsage(input_api, output_api):
1703 """Checks that new logs using org.chromium.base.Log:
1704 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511705 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221706 """
pkotwicza1dd0b002016-05-16 14:41:041707
torne89540622017-03-24 19:41:301708 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041709 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301710 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041711 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301712 # WebView license viewer code cannot depend on //base; used in stub APK.
1713 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1714 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041715 ]
1716
dgnaa68d5e2015-06-10 10:08:221717 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121718 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1719 class_in_base_pattern = input_api.re.compile(
1720 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1721 has_some_log_import_pattern = input_api.re.compile(
1722 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221723 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121724 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221725 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511726 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221727 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221728
Vincent Scheib16d7b272015-09-15 18:09:071729 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221730 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041731 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1732 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121733
dgnaa68d5e2015-06-10 10:08:221734 tag_decl_errors = []
1735 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121736 tag_errors = []
dgn38736db2015-09-18 19:20:511737 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121738 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221739
1740 for f in input_api.AffectedSourceFiles(sources):
1741 file_content = input_api.ReadFile(f)
1742 has_modified_logs = False
1743
1744 # Per line checks
dgn87d9fb62015-06-12 09:15:121745 if (cr_log_import_pattern.search(file_content) or
1746 (class_in_base_pattern.search(file_content) and
1747 not has_some_log_import_pattern.search(file_content))):
1748 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221749 for line_num, line in f.ChangedContents():
1750
1751 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121752 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221753 if match:
1754 has_modified_logs = True
1755
1756 # Make sure it uses "TAG"
1757 if not match.group('tag') == 'TAG':
1758 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121759 else:
1760 # Report non cr Log function calls in changed lines
1761 for line_num, line in f.ChangedContents():
1762 if log_call_pattern.search(line):
1763 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221764
1765 # Per file checks
1766 if has_modified_logs:
1767 # Make sure the tag is using the "cr" prefix and is not too long
1768 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511769 tag_name = match.group('name') if match else None
1770 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221771 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511772 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221773 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511774 elif '.' in tag_name:
1775 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221776
1777 results = []
1778 if tag_decl_errors:
1779 results.append(output_api.PresubmitPromptWarning(
1780 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511781 '"private static final String TAG = "<package tag>".\n'
1782 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221783 tag_decl_errors))
1784
1785 if tag_length_errors:
1786 results.append(output_api.PresubmitError(
1787 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511788 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221789 tag_length_errors))
1790
1791 if tag_errors:
1792 results.append(output_api.PresubmitPromptWarning(
1793 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1794 tag_errors))
1795
dgn87d9fb62015-06-12 09:15:121796 if util_log_errors:
dgn4401aa52015-04-29 16:26:171797 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121798 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1799 util_log_errors))
1800
dgn38736db2015-09-18 19:20:511801 if tag_with_dot_errors:
1802 results.append(output_api.PresubmitPromptWarning(
1803 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1804 tag_with_dot_errors))
1805
dgn4401aa52015-04-29 16:26:171806 return results
1807
1808
Yoland Yanb92fa522017-08-28 17:37:061809def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1810 """Checks that junit.framework.* is no longer used."""
1811 deprecated_junit_framework_pattern = input_api.re.compile(
1812 r'^import junit\.framework\..*;',
1813 input_api.re.MULTILINE)
1814 sources = lambda x: input_api.FilterSourceFile(
1815 x, white_list=(r'.*\.java$',), black_list=None)
1816 errors = []
1817 for f in input_api.AffectedFiles(sources):
1818 for line_num, line in f.ChangedContents():
1819 if deprecated_junit_framework_pattern.search(line):
1820 errors.append("%s:%d" % (f.LocalPath(), line_num))
1821
1822 results = []
1823 if errors:
1824 results.append(output_api.PresubmitError(
1825 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1826 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1827 ' if you have any question.', errors))
1828 return results
1829
1830
1831def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1832 """Checks that if new Java test classes have inheritance.
1833 Either the new test class is JUnit3 test or it is a JUnit4 test class
1834 with a base class, either case is undesirable.
1835 """
1836 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1837
1838 sources = lambda x: input_api.FilterSourceFile(
1839 x, white_list=(r'.*Test\.java$',), black_list=None)
1840 errors = []
1841 for f in input_api.AffectedFiles(sources):
1842 if not f.OldContents():
1843 class_declaration_start_flag = False
1844 for line_num, line in f.ChangedContents():
1845 if class_declaration_pattern.search(line):
1846 class_declaration_start_flag = True
1847 if class_declaration_start_flag and ' extends ' in line:
1848 errors.append('%s:%d' % (f.LocalPath(), line_num))
1849 if '{' in line:
1850 class_declaration_start_flag = False
1851
1852 results = []
1853 if errors:
1854 results.append(output_api.PresubmitPromptWarning(
1855 'The newly created files include Test classes that inherits from base'
1856 ' class. Please do not use inheritance in JUnit4 tests or add new'
1857 ' JUnit3 tests. Contact [email protected] if you have any'
1858 ' questions.', errors))
1859 return results
1860
yolandyan45001472016-12-21 21:12:421861def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1862 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1863 deprecated_annotation_import_pattern = input_api.re.compile(
1864 r'^import android\.test\.suitebuilder\.annotation\..*;',
1865 input_api.re.MULTILINE)
1866 sources = lambda x: input_api.FilterSourceFile(
1867 x, white_list=(r'.*\.java$',), black_list=None)
1868 errors = []
1869 for f in input_api.AffectedFiles(sources):
1870 for line_num, line in f.ChangedContents():
1871 if deprecated_annotation_import_pattern.search(line):
1872 errors.append("%s:%d" % (f.LocalPath(), line_num))
1873
1874 results = []
1875 if errors:
1876 results.append(output_api.PresubmitError(
1877 'Annotations in android.test.suitebuilder.annotation have been'
1878 ' deprecated since API level 24. Please use android.support.test.filters'
1879 ' from //third_party/android_support_test_runner:runner_java instead.'
1880 ' Contact [email protected] if you have any questions.', errors))
1881 return results
1882
1883
agrieve7b6479d82015-10-07 14:24:221884def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1885 """Checks if MDPI assets are placed in a correct directory."""
1886 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1887 ('/res/drawable/' in f.LocalPath() or
1888 '/res/drawable-ldrtl/' in f.LocalPath()))
1889 errors = []
1890 for f in input_api.AffectedFiles(include_deletes=False,
1891 file_filter=file_filter):
1892 errors.append(' %s' % f.LocalPath())
1893
1894 results = []
1895 if errors:
1896 results.append(output_api.PresubmitError(
1897 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1898 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1899 '/res/drawable-ldrtl/.\n'
1900 'Contact [email protected] if you have questions.', errors))
1901 return results
1902
1903
Nate Fischer535972b2017-09-16 01:06:181904def _CheckAndroidWebkitImports(input_api, output_api):
1905 """Checks that code uses org.chromium.base.Callback instead of
1906 android.widget.ValueCallback except in the WebView glue layer.
1907 """
1908 valuecallback_import_pattern = input_api.re.compile(
1909 r'^import android\.webkit\.ValueCallback;$')
1910
1911 errors = []
1912
1913 sources = lambda affected_file: input_api.FilterSourceFile(
1914 affected_file,
1915 black_list=(_EXCLUDED_PATHS +
1916 _TEST_CODE_EXCLUDED_PATHS +
1917 input_api.DEFAULT_BLACK_LIST +
1918 (r'^android_webview[\\\/]glue[\\\/].*',)),
1919 white_list=(r'.*\.java$',))
1920
1921 for f in input_api.AffectedSourceFiles(sources):
1922 for line_num, line in f.ChangedContents():
1923 if valuecallback_import_pattern.search(line):
1924 errors.append("%s:%d" % (f.LocalPath(), line_num))
1925
1926 results = []
1927
1928 if errors:
1929 results.append(output_api.PresubmitError(
1930 'android.webkit.ValueCallback usage is detected outside of the glue'
1931 ' layer. To stay compatible with the support library, android.webkit.*'
1932 ' classes should only be used inside the glue layer and'
1933 ' org.chromium.base.Callback should be used instead.',
1934 errors))
1935
1936 return results
1937
1938
agrievef32bcc72016-04-04 14:57:401939class PydepsChecker(object):
1940 def __init__(self, input_api, pydeps_files):
1941 self._file_cache = {}
1942 self._input_api = input_api
1943 self._pydeps_files = pydeps_files
1944
1945 def _LoadFile(self, path):
1946 """Returns the list of paths within a .pydeps file relative to //."""
1947 if path not in self._file_cache:
1948 with open(path) as f:
1949 self._file_cache[path] = f.read()
1950 return self._file_cache[path]
1951
1952 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1953 """Returns an interable of paths within the .pydep, relativized to //."""
1954 os_path = self._input_api.os_path
1955 pydeps_dir = os_path.dirname(pydeps_path)
1956 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1957 if not l.startswith('*'))
1958 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1959
1960 def _CreateFilesToPydepsMap(self):
1961 """Returns a map of local_path -> list_of_pydeps."""
1962 ret = {}
1963 for pydep_local_path in self._pydeps_files:
1964 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1965 ret.setdefault(path, []).append(pydep_local_path)
1966 return ret
1967
1968 def ComputeAffectedPydeps(self):
1969 """Returns an iterable of .pydeps files that might need regenerating."""
1970 affected_pydeps = set()
1971 file_to_pydeps_map = None
1972 for f in self._input_api.AffectedFiles(include_deletes=True):
1973 local_path = f.LocalPath()
1974 if local_path == 'DEPS':
1975 return self._pydeps_files
1976 elif local_path.endswith('.pydeps'):
1977 if local_path in self._pydeps_files:
1978 affected_pydeps.add(local_path)
1979 elif local_path.endswith('.py'):
1980 if file_to_pydeps_map is None:
1981 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1982 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1983 return affected_pydeps
1984
1985 def DetermineIfStale(self, pydeps_path):
1986 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411987 import difflib
agrievef32bcc72016-04-04 14:57:401988 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1989 cmd = old_pydeps_data[1][1:].strip()
1990 new_pydeps_data = self._input_api.subprocess.check_output(
1991 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411992 old_contents = old_pydeps_data[2:]
1993 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401994 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411995 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401996
1997
1998def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1999 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:002000 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:282001 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
2002 # Mac, so skip it on other platforms.
2003 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:002004 return []
agrievef32bcc72016-04-04 14:57:402005 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
2006 is_android = input_api.os_path.exists('third_party/android_tools')
2007 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
2008 results = []
2009 # First, check for new / deleted .pydeps.
2010 for f in input_api.AffectedFiles(include_deletes=True):
2011 if f.LocalPath().endswith('.pydeps'):
2012 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
2013 results.append(output_api.PresubmitError(
2014 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2015 'remove %s' % f.LocalPath()))
2016 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
2017 results.append(output_api.PresubmitError(
2018 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
2019 'include %s' % f.LocalPath()))
2020
2021 if results:
2022 return results
2023
2024 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
2025
2026 for pydep_path in checker.ComputeAffectedPydeps():
2027 try:
phajdan.jr0d9878552016-11-04 10:49:412028 result = checker.DetermineIfStale(pydep_path)
2029 if result:
2030 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402031 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412032 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2033 'To regenerate, run:\n\n %s' %
2034 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402035 except input_api.subprocess.CalledProcessError as error:
2036 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2037 long_text=error.output)]
2038
2039 return results
2040
2041
glidere61efad2015-02-18 17:39:432042def _CheckSingletonInHeaders(input_api, output_api):
2043 """Checks to make sure no header files have |Singleton<|."""
2044 def FileFilter(affected_file):
2045 # It's ok for base/memory/singleton.h to have |Singleton<|.
2046 black_list = (_EXCLUDED_PATHS +
2047 input_api.DEFAULT_BLACK_LIST +
2048 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2049 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2050
sergeyu34d21222015-09-16 00:11:442051 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432052 files = []
2053 for f in input_api.AffectedSourceFiles(FileFilter):
2054 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2055 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2056 contents = input_api.ReadFile(f)
2057 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242058 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432059 pattern.search(line)):
2060 files.append(f)
2061 break
2062
2063 if files:
yolandyandaabc6d2016-04-18 18:29:392064 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442065 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432066 'Please move them to an appropriate source file so that the ' +
2067 'template gets instantiated in a single compilation unit.',
2068 files) ]
2069 return []
2070
2071
[email protected]fd20b902014-05-09 02:14:532072_DEPRECATED_CSS = [
2073 # Values
2074 ( "-webkit-box", "flex" ),
2075 ( "-webkit-inline-box", "inline-flex" ),
2076 ( "-webkit-flex", "flex" ),
2077 ( "-webkit-inline-flex", "inline-flex" ),
2078 ( "-webkit-min-content", "min-content" ),
2079 ( "-webkit-max-content", "max-content" ),
2080
2081 # Properties
2082 ( "-webkit-background-clip", "background-clip" ),
2083 ( "-webkit-background-origin", "background-origin" ),
2084 ( "-webkit-background-size", "background-size" ),
2085 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442086 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532087
2088 # Functions
2089 ( "-webkit-gradient", "gradient" ),
2090 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2091 ( "-webkit-linear-gradient", "linear-gradient" ),
2092 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2093 ( "-webkit-radial-gradient", "radial-gradient" ),
2094 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2095]
2096
dbeam1ec68ac2016-12-15 05:22:242097def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532098 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252099 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342100 documentation and iOS CSS for dom distiller
2101 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252102 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532103 results = []
dbeam070cfe62014-10-22 06:44:022104 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252105 black_list = (_EXCLUDED_PATHS +
2106 _TEST_CODE_EXCLUDED_PATHS +
2107 input_api.DEFAULT_BLACK_LIST +
2108 (r"^chrome/common/extensions/docs",
2109 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342110 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442111 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252112 r"^native_client_sdk"))
2113 file_filter = lambda f: input_api.FilterSourceFile(
2114 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532115 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2116 for line_num, line in fpath.ChangedContents():
2117 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022118 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532119 results.append(output_api.PresubmitError(
2120 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2121 (fpath.LocalPath(), line_num, deprecated_value, value)))
2122 return results
2123
mohan.reddyf21db962014-10-16 12:26:472124
dbeam070cfe62014-10-22 06:44:022125_DEPRECATED_JS = [
2126 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2127 ( "__defineGetter__", "Object.defineProperty" ),
2128 ( "__defineSetter__", "Object.defineProperty" ),
2129]
2130
dbeam1ec68ac2016-12-15 05:22:242131def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022132 """Make sure that we don't use deprecated JS in Chrome code."""
2133 results = []
2134 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2135 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2136 input_api.DEFAULT_BLACK_LIST)
2137 file_filter = lambda f: input_api.FilterSourceFile(
2138 f, white_list=file_inclusion_pattern, black_list=black_list)
2139 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2140 for lnum, line in fpath.ChangedContents():
2141 for (deprecated, replacement) in _DEPRECATED_JS:
2142 if deprecated in line:
2143 results.append(output_api.PresubmitError(
2144 "%s:%d: Use of deprecated JS %s, use %s instead" %
2145 (fpath.LocalPath(), lnum, deprecated, replacement)))
2146 return results
2147
dpapadd651231d82017-07-21 02:44:472148def _CheckForRiskyJsArrowFunction(line_number, line):
2149 if ' => ' in line:
2150 return "line %d, is using an => (arrow) function\n %s\n" % (
2151 line_number, line)
2152 return ''
2153
2154def _CheckForRiskyJsConstLet(input_api, line_number, line):
2155 if input_api.re.match('^\s*(const|let)\s', line):
2156 return "line %d, is using const/let keyword\n %s\n" % (
2157 line_number, line)
2158 return ''
dbeam070cfe62014-10-22 06:44:022159
dbeam1ec68ac2016-12-15 05:22:242160def _CheckForRiskyJsFeatures(input_api, output_api):
2161 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002162 # 'ui/webui/resources/cr_components are not allowed on ios'
2163 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572164 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002165 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472166 results = []
dbeam1ec68ac2016-12-15 05:22:242167 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472168 arrow_error_lines = []
2169 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242170 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472171 arrow_error_lines += filter(None, [
2172 _CheckForRiskyJsArrowFunction(lnum, line),
2173 ])
dbeam1ec68ac2016-12-15 05:22:242174
dpapadd651231d82017-07-21 02:44:472175 const_let_error_lines += filter(None, [
2176 _CheckForRiskyJsConstLet(input_api, lnum, line),
2177 ])
dbeam1ec68ac2016-12-15 05:22:242178
dpapadd651231d82017-07-21 02:44:472179 if arrow_error_lines:
2180 arrow_error_lines = map(
2181 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2182 results.append(
2183 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2184"""
2185Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242186%s
2187Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2188https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472189""" % f.LocalPath()
2190 ])))
dbeam1ec68ac2016-12-15 05:22:242191
dpapadd651231d82017-07-21 02:44:472192 if const_let_error_lines:
2193 const_let_error_lines = map(
2194 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2195 results.append(
2196 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2197"""
2198Use of const/let keywords detected in:
2199%s
2200Please ensure your code does not run on iOS9 because const/let is not fully
2201supported.
2202https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2203https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2204""" % f.LocalPath()
2205 ])))
2206
2207 return results
dbeam1ec68ac2016-12-15 05:22:242208
rlanday6802cf632017-05-30 17:48:362209def _CheckForRelativeIncludes(input_api, output_api):
2210 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2211 import sys
2212 original_sys_path = sys.path
2213 try:
2214 sys.path = sys.path + [input_api.os_path.join(
2215 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2216 from cpp_checker import CppChecker
2217 finally:
2218 # Restore sys.path to what it was before.
2219 sys.path = original_sys_path
2220
2221 bad_files = {}
2222 for f in input_api.AffectedFiles(include_deletes=False):
2223 if (f.LocalPath().startswith('third_party') and
2224 not f.LocalPath().startswith('third_party/WebKit') and
2225 not f.LocalPath().startswith('third_party\\WebKit')):
2226 continue
2227
2228 if not CppChecker.IsCppFile(f.LocalPath()):
2229 continue
2230
2231 relative_includes = [line for line_num, line in f.ChangedContents()
2232 if "#include" in line and "../" in line]
2233 if not relative_includes:
2234 continue
2235 bad_files[f.LocalPath()] = relative_includes
2236
2237 if not bad_files:
2238 return []
2239
2240 error_descriptions = []
2241 for file_path, bad_lines in bad_files.iteritems():
2242 error_description = file_path
2243 for line in bad_lines:
2244 error_description += '\n ' + line
2245 error_descriptions.append(error_description)
2246
2247 results = []
2248 results.append(output_api.PresubmitError(
2249 'You added one or more relative #include paths (including "../").\n'
2250 'These shouldn\'t be used because they can be used to include headers\n'
2251 'from code that\'s not correctly specified as a dependency in the\n'
2252 'relevant BUILD.gn file(s).',
2253 error_descriptions))
2254
2255 return results
2256
Takeshi Yoshinoe387aa32017-08-02 13:16:132257
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202258def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2259 if not isinstance(key, ast.Str):
2260 return 'Key at line %d must be a string literal' % key.lineno
2261 if not isinstance(value, ast.Dict):
2262 return 'Value at line %d must be a dict' % value.lineno
2263 if len(value.keys) != 1:
2264 return 'Dict at line %d must have single entry' % value.lineno
2265 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2266 return (
2267 'Entry at line %d must have a string literal \'filepath\' as key' %
2268 value.lineno)
2269 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132270
Takeshi Yoshinoe387aa32017-08-02 13:16:132271
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202272def _CheckWatchlistsEntrySyntax(key, value, ast):
2273 if not isinstance(key, ast.Str):
2274 return 'Key at line %d must be a string literal' % key.lineno
2275 if not isinstance(value, ast.List):
2276 return 'Value at line %d must be a list' % value.lineno
2277 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132278
Takeshi Yoshinoe387aa32017-08-02 13:16:132279
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202280def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2281 mismatch_template = (
2282 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2283 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132284
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202285 i = 0
2286 last_key = ''
2287 while True:
2288 if i >= len(wd_dict.keys):
2289 if i >= len(w_dict.keys):
2290 return None
2291 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2292 elif i >= len(w_dict.keys):
2293 return (
2294 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132295
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202296 wd_key = wd_dict.keys[i]
2297 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132298
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202299 result = _CheckWatchlistDefinitionsEntrySyntax(
2300 wd_key, wd_dict.values[i], ast)
2301 if result is not None:
2302 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132303
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202304 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2305 if result is not None:
2306 return 'Bad entry in WATCHLISTS dict: %s' % result
2307
2308 if wd_key.s != w_key.s:
2309 return mismatch_template % (
2310 '%s at line %d' % (wd_key.s, wd_key.lineno),
2311 '%s at line %d' % (w_key.s, w_key.lineno))
2312
2313 if wd_key.s < last_key:
2314 return (
2315 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2316 (wd_key.lineno, w_key.lineno))
2317 last_key = wd_key.s
2318
2319 i = i + 1
2320
2321
2322def _CheckWATCHLISTSSyntax(expression, ast):
2323 if not isinstance(expression, ast.Expression):
2324 return 'WATCHLISTS file must contain a valid expression'
2325 dictionary = expression.body
2326 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2327 return 'WATCHLISTS file must have single dict with exactly two entries'
2328
2329 first_key = dictionary.keys[0]
2330 first_value = dictionary.values[0]
2331 second_key = dictionary.keys[1]
2332 second_value = dictionary.values[1]
2333
2334 if (not isinstance(first_key, ast.Str) or
2335 first_key.s != 'WATCHLIST_DEFINITIONS' or
2336 not isinstance(first_value, ast.Dict)):
2337 return (
2338 'The first entry of the dict in WATCHLISTS file must be '
2339 'WATCHLIST_DEFINITIONS dict')
2340
2341 if (not isinstance(second_key, ast.Str) or
2342 second_key.s != 'WATCHLISTS' or
2343 not isinstance(second_value, ast.Dict)):
2344 return (
2345 'The second entry of the dict in WATCHLISTS file must be '
2346 'WATCHLISTS dict')
2347
2348 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132349
2350
2351def _CheckWATCHLISTS(input_api, output_api):
2352 for f in input_api.AffectedFiles(include_deletes=False):
2353 if f.LocalPath() == 'WATCHLISTS':
2354 contents = input_api.ReadFile(f, 'r')
2355
2356 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202357 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132358 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202359 # Get an AST tree for it and scan the tree for detailed style checking.
2360 expression = input_api.ast.parse(
2361 contents, filename='WATCHLISTS', mode='eval')
2362 except ValueError as e:
2363 return [output_api.PresubmitError(
2364 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2365 except SyntaxError as e:
2366 return [output_api.PresubmitError(
2367 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2368 except TypeError as e:
2369 return [output_api.PresubmitError(
2370 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132371
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202372 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2373 if result is not None:
2374 return [output_api.PresubmitError(result)]
2375 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132376
2377 return []
2378
2379
dgnaa68d5e2015-06-10 10:08:222380def _AndroidSpecificOnUploadChecks(input_api, output_api):
2381 """Groups checks that target android code."""
2382 results = []
dgnaa68d5e2015-06-10 10:08:222383 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222384 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292385 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062386 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2387 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422388 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:182389 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222390 return results
2391
2392
[email protected]22c9bd72011-03-27 16:47:392393def _CommonChecks(input_api, output_api):
2394 """Checks common to both upload and commit."""
2395 results = []
2396 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382397 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542398 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582399 results.extend(
2400 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192401 results.extend(
[email protected]760deea2013-12-10 19:33:492402 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542403 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182404 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522405 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222406 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442407 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592408 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062409 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122410 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182411 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222412 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302413 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492414 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032415 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492416 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442417 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272418 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072419 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542420 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442421 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392422 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552423 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042424 results.extend(
2425 input_api.canned_checks.CheckChangeHasNoTabs(
2426 input_api,
2427 output_api,
2428 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402429 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162430 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082431 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242432 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2433 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472434 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042435 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232436 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432437 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402438 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152439 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172440 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502441 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242442 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362443 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132444 results.extend(_CheckWATCHLISTS(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242445
2446 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2447 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2448 input_api, output_api,
2449 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382450 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392451 return results
[email protected]1f7b4172010-01-28 01:17:342452
[email protected]b337cb5b2011-01-23 21:24:052453
[email protected]b8079ae4a2012-12-05 19:56:492454def _CheckPatchFiles(input_api, output_api):
2455 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2456 if f.LocalPath().endswith(('.orig', '.rej'))]
2457 if problems:
2458 return [output_api.PresubmitError(
2459 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032460 else:
2461 return []
[email protected]b8079ae4a2012-12-05 19:56:492462
2463
Kent Tamura5a8755d2017-06-29 23:37:072464def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212465 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2466 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2467 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072468 include_re = input_api.re.compile(
2469 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2470 extension_re = input_api.re.compile(r'\.[a-z]+$')
2471 errors = []
2472 for f in input_api.AffectedFiles():
2473 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2474 continue
2475 found_line_number = None
2476 found_macro = None
2477 for line_num, line in f.ChangedContents():
2478 match = macro_re.search(line)
2479 if match:
2480 found_line_number = line_num
2481 found_macro = match.group(2)
2482 break
2483 if not found_line_number:
2484 continue
2485
2486 found_include = False
2487 for line in f.NewContents():
2488 if include_re.search(line):
2489 found_include = True
2490 break
2491 if found_include:
2492 continue
2493
2494 if not f.LocalPath().endswith('.h'):
2495 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2496 try:
2497 content = input_api.ReadFile(primary_header_path, 'r')
2498 if include_re.search(content):
2499 continue
2500 except IOError:
2501 pass
2502 errors.append('%s:%d %s macro is used without including build/'
2503 'build_config.h.'
2504 % (f.LocalPath(), found_line_number, found_macro))
2505 if errors:
2506 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2507 return []
2508
2509
[email protected]b00342e7f2013-03-26 16:21:542510def _DidYouMeanOSMacro(bad_macro):
2511 try:
2512 return {'A': 'OS_ANDROID',
2513 'B': 'OS_BSD',
2514 'C': 'OS_CHROMEOS',
2515 'F': 'OS_FREEBSD',
2516 'L': 'OS_LINUX',
2517 'M': 'OS_MACOSX',
2518 'N': 'OS_NACL',
2519 'O': 'OS_OPENBSD',
2520 'P': 'OS_POSIX',
2521 'S': 'OS_SOLARIS',
2522 'W': 'OS_WIN'}[bad_macro[3].upper()]
2523 except KeyError:
2524 return ''
2525
2526
2527def _CheckForInvalidOSMacrosInFile(input_api, f):
2528 """Check for sensible looking, totally invalid OS macros."""
2529 preprocessor_statement = input_api.re.compile(r'^\s*#')
2530 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2531 results = []
2532 for lnum, line in f.ChangedContents():
2533 if preprocessor_statement.search(line):
2534 for match in os_macro.finditer(line):
2535 if not match.group(1) in _VALID_OS_MACROS:
2536 good = _DidYouMeanOSMacro(match.group(1))
2537 did_you_mean = ' (did you mean %s?)' % good if good else ''
2538 results.append(' %s:%d %s%s' % (f.LocalPath(),
2539 lnum,
2540 match.group(1),
2541 did_you_mean))
2542 return results
2543
2544
2545def _CheckForInvalidOSMacros(input_api, output_api):
2546 """Check all affected files for invalid OS macros."""
2547 bad_macros = []
2548 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472549 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542550 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2551
2552 if not bad_macros:
2553 return []
2554
2555 return [output_api.PresubmitError(
2556 'Possibly invalid OS macro[s] found. Please fix your code\n'
2557 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2558
lliabraa35bab3932014-10-01 12:16:442559
2560def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2561 """Check all affected files for invalid "if defined" macros."""
2562 ALWAYS_DEFINED_MACROS = (
2563 "TARGET_CPU_PPC",
2564 "TARGET_CPU_PPC64",
2565 "TARGET_CPU_68K",
2566 "TARGET_CPU_X86",
2567 "TARGET_CPU_ARM",
2568 "TARGET_CPU_MIPS",
2569 "TARGET_CPU_SPARC",
2570 "TARGET_CPU_ALPHA",
2571 "TARGET_IPHONE_SIMULATOR",
2572 "TARGET_OS_EMBEDDED",
2573 "TARGET_OS_IPHONE",
2574 "TARGET_OS_MAC",
2575 "TARGET_OS_UNIX",
2576 "TARGET_OS_WIN32",
2577 )
2578 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2579 results = []
2580 for lnum, line in f.ChangedContents():
2581 for match in ifdef_macro.finditer(line):
2582 if match.group(1) in ALWAYS_DEFINED_MACROS:
2583 always_defined = ' %s is always defined. ' % match.group(1)
2584 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2585 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2586 lnum,
2587 always_defined,
2588 did_you_mean))
2589 return results
2590
2591
2592def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2593 """Check all affected files for invalid "if defined" macros."""
2594 bad_macros = []
2595 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212596 if f.LocalPath().startswith('third_party/sqlite/'):
2597 continue
lliabraa35bab3932014-10-01 12:16:442598 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2599 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2600
2601 if not bad_macros:
2602 return []
2603
2604 return [output_api.PresubmitError(
2605 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2606 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2607 bad_macros)]
2608
2609
mlamouria82272622014-09-16 18:45:042610def _CheckForIPCRules(input_api, output_api):
2611 """Check for same IPC rules described in
2612 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2613 """
2614 base_pattern = r'IPC_ENUM_TRAITS\('
2615 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2616 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2617
2618 problems = []
2619 for f in input_api.AffectedSourceFiles(None):
2620 local_path = f.LocalPath()
2621 if not local_path.endswith('.h'):
2622 continue
2623 for line_number, line in f.ChangedContents():
2624 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2625 problems.append(
2626 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2627
2628 if problems:
2629 return [output_api.PresubmitPromptWarning(
2630 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2631 else:
2632 return []
2633
[email protected]b00342e7f2013-03-26 16:21:542634
mostynbb639aca52015-01-07 20:31:232635def _CheckForWindowsLineEndings(input_api, output_api):
2636 """Check source code and known ascii text files for Windows style line
2637 endings.
2638 """
earthdok1b5e0ee2015-03-10 15:19:102639 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232640
2641 file_inclusion_pattern = (
2642 known_text_files,
2643 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2644 )
2645
2646 filter = lambda f: input_api.FilterSourceFile(
2647 f, white_list=file_inclusion_pattern, black_list=None)
2648 files = [f.LocalPath() for f in
2649 input_api.AffectedSourceFiles(filter)]
2650
2651 problems = []
2652
2653 for file in files:
2654 fp = open(file, 'r')
2655 for line in fp:
2656 if line.endswith('\r\n'):
2657 problems.append(file)
2658 break
2659 fp.close()
2660
2661 if problems:
2662 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2663 'these files to contain Windows style line endings?\n' +
2664 '\n'.join(problems))]
2665
2666 return []
2667
2668
pastarmovj89f7ee12016-09-20 14:58:132669def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2670 lint_filters=None, verbose_level=None):
2671 """Checks that all source files use SYSLOG properly."""
2672 syslog_files = []
2673 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562674 for line_number, line in f.ChangedContents():
2675 if 'SYSLOG' in line:
2676 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2677
pastarmovj89f7ee12016-09-20 14:58:132678 if syslog_files:
2679 return [output_api.PresubmitPromptWarning(
2680 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2681 ' calls.\nFiles to check:\n', items=syslog_files)]
2682 return []
2683
2684
[email protected]1f7b4172010-01-28 01:17:342685def CheckChangeOnUpload(input_api, output_api):
2686 results = []
2687 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472688 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282689 results.extend(
jam93a6ee792017-02-08 23:59:222690 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192691 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222692 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132693 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162694 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542695 return results
[email protected]ca8d19842009-02-19 16:33:122696
2697
[email protected]1bfb8322014-04-23 01:02:412698def GetTryServerMasterForBot(bot):
2699 """Returns the Try Server master for the given bot.
2700
[email protected]0bb112362014-07-26 04:38:322701 It tries to guess the master from the bot name, but may still fail
2702 and return None. There is no longer a default master.
2703 """
2704 # Potentially ambiguous bot names are listed explicitly.
2705 master_map = {
tandriie5587792016-07-14 00:34:502706 'chromium_presubmit': 'master.tryserver.chromium.linux',
2707 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412708 }
[email protected]0bb112362014-07-26 04:38:322709 master = master_map.get(bot)
2710 if not master:
wnwen4fbaab82016-05-25 12:54:362711 if 'android' in bot:
tandriie5587792016-07-14 00:34:502712 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362713 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502714 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322715 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502716 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322717 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502718 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322719 return master
[email protected]1bfb8322014-04-23 01:02:412720
2721
[email protected]ca8d19842009-02-19 16:33:122722def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542723 results = []
[email protected]1f7b4172010-01-28 01:17:342724 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542725 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272726 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342727 input_api,
2728 output_api,
[email protected]2fdd1f362013-01-16 03:56:032729 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272730
jam93a6ee792017-02-08 23:59:222731 results.extend(
2732 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542733 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2734 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412735 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2736 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542737 return results