blob: 08a906ccc1fbc9ea6ef55e17529980277d0ed254 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d19842009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d19842009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
primiano0166ccc82015-10-06 12:12:2819 r"^third_party[\\\/]WebKit[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
vapierb2053f542017-03-09 19:46:1026 r"tools[\\\/]md_browser[\\\/].*\.css$",
ehmaldonado78eee2ed2017-03-28 13:16:5427 # Test pages for WebRTC telemetry tests.
28 r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4029)
[email protected]ca8d19842009-02-19 16:33:1230
wnwenbdc444e2016-05-25 13:44:1531
[email protected]06e6d0ff2012-12-11 01:36:4432# Fragment of a regular expression that matches C++ and Objective-C++
33# implementation files.
34_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
35
wnwenbdc444e2016-05-25 13:44:1536
[email protected]06e6d0ff2012-12-11 01:36:4437# Regular expression that matches code only used for test binaries
38# (best effort).
39_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4940 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4441 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
sdefresne1fccb0a2016-12-19 08:10:5342 r'.+_(api|browser|eg|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1243 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4444 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4945 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0546 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4947 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4748 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4949 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0850 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4951 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4452)
[email protected]ca8d19842009-02-19 16:33:1253
wnwenbdc444e2016-05-25 13:44:1554
[email protected]eea609a2011-11-18 13:10:1255_TEST_ONLY_WARNING = (
56 'You might be calling functions intended only for testing from\n'
57 'production code. It is OK to ignore this warning if you know what\n'
58 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5859 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1260
61
[email protected]cf9b78f2012-11-14 11:40:2862_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4063 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2164 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
65 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2866
wnwenbdc444e2016-05-25 13:44:1567
[email protected]127f18ec2012-06-16 05:05:5968_BANNED_OBJC_FUNCTIONS = (
69 (
70 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2071 (
72 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5973 'prohibited. Please use CrTrackingArea instead.',
74 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
75 ),
76 False,
77 ),
78 (
[email protected]eaae1972014-04-16 04:17:2679 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2080 (
81 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5982 'instead.',
83 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
84 ),
85 False,
86 ),
87 (
88 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2089 (
90 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5991 'Please use |convertPoint:(point) fromView:nil| instead.',
92 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
93 ),
94 True,
95 ),
96 (
97 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:2098 (
99 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59100 'Please use |convertPoint:(point) toView:nil| instead.',
101 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
102 ),
103 True,
104 ),
105 (
106 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20107 (
108 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59109 'Please use |convertRect:(point) fromView:nil| instead.',
110 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
111 ),
112 True,
113 ),
114 (
115 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20116 (
117 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59118 'Please use |convertRect:(point) toView:nil| instead.',
119 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
120 ),
121 True,
122 ),
123 (
124 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20125 (
126 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59127 'Please use |convertSize:(point) fromView:nil| instead.',
128 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
129 ),
130 True,
131 ),
132 (
133 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20134 (
135 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59136 'Please use |convertSize:(point) toView:nil| instead.',
137 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
138 ),
139 True,
140 ),
jif65398702016-10-27 10:19:48141 (
142 r"/\s+UTF8String\s*]",
143 (
144 'The use of -[NSString UTF8String] is dangerous as it can return null',
145 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
146 'Please use |SysNSStringToUTF8| instead.',
147 ),
148 True,
149 ),
[email protected]127f18ec2012-06-16 05:05:59150)
151
152
153_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20154 # Make sure that gtest's FRIEND_TEST() macro is not used; the
155 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30156 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20157 (
thomasandersone7caaa9b2017-03-29 19:22:53158 r'\bNULL\b',
159 (
160 'New code should not use NULL. Use nullptr instead.',
161 ),
162 True,
163 (),
164 ),
165 (
[email protected]23e6cbc2012-06-16 18:51:20166 'FRIEND_TEST(',
167 (
[email protected]e3c945502012-06-26 20:01:49168 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20169 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
170 ),
171 False,
[email protected]7345da02012-11-27 14:31:49172 (),
[email protected]23e6cbc2012-06-16 18:51:20173 ),
174 (
thomasanderson4b569052016-09-14 20:15:53175 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
176 (
177 'Chrome clients wishing to select events on X windows should use',
178 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
179 'you are selecting events from the GPU process, or if you are using',
180 'an XDisplay other than gfx::GetXDisplay().',
181 ),
182 True,
183 (
184 r"^ui[\\\/]gl[\\\/].*\.cc$",
185 r"^media[\\\/]gpu[\\\/].*\.cc$",
186 r"^gpu[\\\/].*\.cc$",
187 ),
188 ),
189 (
thomasandersone043e3ce2017-06-08 00:43:20190 r'XInternAtom|xcb_intern_atom',
191 (
thomasanderson11aa41d2017-06-08 22:22:38192 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20193 ),
194 True,
195 (
thomasanderson11aa41d2017-06-08 22:22:38196 r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$",
197 r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20198 r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$",
199 ),
200 ),
201 (
[email protected]23e6cbc2012-06-16 18:51:20202 'ScopedAllowIO',
203 (
satoruxe1396f8a2017-06-01 06:40:39204 'New production code should not use ScopedAllowIO (using it in',
Marijn Kruisselbrink085ef092017-07-12 23:56:55205 'tests is fine). Post a task to a MayBlock task runner instead.',
[email protected]23e6cbc2012-06-16 18:51:20206 ),
[email protected]e3c945502012-06-26 20:01:49207 True,
[email protected]7345da02012-11-27 14:31:49208 (
Marijn Kruisselbrink085ef092017-07-12 23:56:55209 r"^.*(browser|unit)(|_)test[a-z_]*\.cc$",
hajimehoshi2acea432017-03-08 08:55:37210 r"^base[\\\/]memory[\\\/]shared_memory_posix\.cc$",
rayb0088ee52017-04-26 22:35:08211 r"^base[\\\/]process[\\\/]internal_aix\.cc$",
nyad2c548b2015-12-09 03:22:32212 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10213 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
tfarina0923ac52015-01-07 03:21:22214 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
rdevlin.cronin62018a12017-06-22 17:34:06215 r"^chrome[\\\/]browser[\\\/]extensions[\\\/]" +
216 r"chrome_test_extension_loader.cc$",
sky0e07a142016-03-25 21:27:31217 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
philipj3f9d5bde2014-08-28 14:09:09218 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49219 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
220 r"test_info_extractor\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41221 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
222 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25223 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
miu8e0e80c2017-05-31 03:35:57224 r"^media[\\\/]cast[\\\/]test[\\\/]utility[\\\/]" +
225 r"standalone_cast_environment\.cc$",
jamesra03ae492014-10-03 04:26:48226 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
227 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01228 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25229 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
230 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
231 r"embedded_test_server\.cc$",
232 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
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 (
Francois Dorayd7c671722017-08-01 17:31:39337 r'/(WebThread|BrowserThread)::GetBlockingPool',
fdorayc4ac18d2017-05-01 21:39:59338 (
339 'Use base/task_scheduler/post_task.h instead of the blocking pool. See',
340 'mapping between both APIs in content/public/browser/browser_thread.h.',
341 'For questions, contact base/task_scheduler/OWNERS.',
342 ),
343 True,
344 (),
345 ),
gabd52c912a2017-05-11 04:15:59346 (
Kevin Marshall342ddd62017-08-24 17:22:36347 r'/(WebThread|BrowserThread)::(FILE|FILE_USER_BLOCKING|DB|CACHE)',
Gabriel Charette664e4482017-06-13 19:55:29348 (
349 'The non-UI/IO BrowserThreads are deprecated, please migrate this',
350 'code to TaskScheduler. See https://goo.gl/mDSxKl for details.',
351 'For questions, contact base/task_scheduler/OWNERS.',
352 ),
353 True,
354 (),
355 ),
356 (
gabd52c912a2017-05-11 04:15:59357 'base::SequenceChecker',
358 (
359 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
360 ),
361 False,
362 (),
363 ),
364 (
365 'base::ThreadChecker',
366 (
367 'Consider using THREAD_CHECKER macros instead of the class directly.',
368 ),
369 False,
370 (),
371 ),
dbeamb6f4fde2017-06-15 04:03:06372 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06373 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
374 (
375 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
376 'deprecated (http://crbug.com/634507). Please avoid converting away',
377 'from the Time types in Chromium code, especially if any math is',
378 'being done on time values. For interfacing with platform/library',
379 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
380 'type converter methods instead. For faking TimeXXX values (for unit',
381 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
382 'other use cases, please contact base/time/OWNERS.',
383 ),
384 False,
385 (),
386 ),
387 (
dbeamb6f4fde2017-06-15 04:03:06388 'CallJavascriptFunctionUnsafe',
389 (
390 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
391 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
392 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
393 ),
394 False,
395 (
396 r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$',
397 r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$',
398 r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$',
399 ),
400 ),
dskiba1474c2bfd62017-07-20 02:19:24401 (
402 'leveldb::DB::Open',
403 (
404 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
405 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
406 "Chrome's tracing, making their memory usage visible.",
407 ),
408 True,
409 (
410 r'^third_party/leveldatabase/.*\.(cc|h)$',
411 ),
Gabriel Charette0592c3a2017-07-26 12:02:04412 ),
413 (
Gabriel Charetted9839bc2017-07-29 14:17:47414 'MessageLoop::QuitWhenIdleClosure',
Gabriel Charette0592c3a2017-07-26 12:02:04415 (
Robert Liao64b7ab22017-08-04 23:03:43416 'MessageLoop::QuitWhenIdleClosure is deprecated. Please migrate to',
417 'Runloop.',
Gabriel Charette0592c3a2017-07-26 12:02:04418 ),
419 True,
420 (),
Gabriel Charetted9839bc2017-07-29 14:17:47421 ),
422 (
423 'RunLoop::QuitCurrent',
424 (
Robert Liao64b7ab22017-08-04 23:03:43425 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
426 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47427 ),
428 True,
429 (),
Gabriel Charettea44975052017-08-21 23:14:04430 ),
431 (
432 'base::ScopedMockTimeMessageLoopTaskRunner',
433 (
434 'ScopedMockTimeMessageLoopTaskRunner is deprecated.',
435 ),
436 True,
437 (),
dskiba1474c2bfd62017-07-20 02:19:24438 )
[email protected]127f18ec2012-06-16 05:05:59439)
440
wnwenbdc444e2016-05-25 13:44:15441
mlamouria82272622014-09-16 18:45:04442_IPC_ENUM_TRAITS_DEPRECATED = (
443 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
444 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
445
[email protected]127f18ec2012-06-16 05:05:59446
Sean Kau46e29bc2017-08-28 16:31:16447# These paths contain test data and other known invalid JSON files.
448_KNOWN_INVALID_JSON_FILE_PATTERNS = [
449 r'test[\\\/]data[\\\/]',
450 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
451 r'^third_party[\\\/]protobuf[\\\/]',
452]
453
454
[email protected]b00342e7f2013-03-26 16:21:54455_VALID_OS_MACROS = (
456 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08457 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54458 'OS_ANDROID',
459 'OS_BSD',
460 'OS_CAT', # For testing.
461 'OS_CHROMEOS',
462 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37463 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54464 'OS_IOS',
465 'OS_LINUX',
466 'OS_MACOSX',
467 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21468 'OS_NACL_NONSFI',
469 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12470 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54471 'OS_OPENBSD',
472 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37473 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54474 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54475 'OS_WIN',
476)
477
478
agrievef32bcc72016-04-04 14:57:40479_ANDROID_SPECIFIC_PYDEPS_FILES = [
480 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04481 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58482 'build/secondary/third_party/android_platform/'
483 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19484 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40485]
486
wnwenbdc444e2016-05-25 13:44:15487
agrievef32bcc72016-04-04 14:57:40488_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40489]
490
wnwenbdc444e2016-05-25 13:44:15491
agrievef32bcc72016-04-04 14:57:40492_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
493
494
[email protected]55459852011-08-10 15:17:19495def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
496 """Attempts to prevent use of functions intended only for testing in
497 non-testing code. For now this is just a best-effort implementation
498 that ignores header files and may have some false positives. A
499 better implementation would probably need a proper C++ parser.
500 """
501 # We only scan .cc files and the like, as the declaration of
502 # for-testing functions in header files are hard to distinguish from
503 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44504 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19505
jochenc0d4808c2015-07-27 09:25:42506 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19507 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09508 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19509 exclusion_pattern = input_api.re.compile(
510 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
511 base_function_pattern, base_function_pattern))
512
513 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44514 black_list = (_EXCLUDED_PATHS +
515 _TEST_CODE_EXCLUDED_PATHS +
516 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19517 return input_api.FilterSourceFile(
518 affected_file,
519 white_list=(file_inclusion_pattern, ),
520 black_list=black_list)
521
522 problems = []
523 for f in input_api.AffectedSourceFiles(FilterFile):
524 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24525 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03526 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46527 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03528 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19529 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03530 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19531
532 if problems:
[email protected]f7051d52013-04-02 18:31:42533 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03534 else:
535 return []
[email protected]55459852011-08-10 15:17:19536
537
[email protected]10689ca2011-09-02 02:31:54538def _CheckNoIOStreamInHeaders(input_api, output_api):
539 """Checks to make sure no .h files include <iostream>."""
540 files = []
541 pattern = input_api.re.compile(r'^#include\s*<iostream>',
542 input_api.re.MULTILINE)
543 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
544 if not f.LocalPath().endswith('.h'):
545 continue
546 contents = input_api.ReadFile(f)
547 if pattern.search(contents):
548 files.append(f)
549
550 if len(files):
yolandyandaabc6d2016-04-18 18:29:39551 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06552 'Do not #include <iostream> in header files, since it inserts static '
553 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54554 '#include <ostream>. See http://crbug.com/94794',
555 files) ]
556 return []
557
558
[email protected]72df4e782012-06-21 16:28:18559def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52560 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18561 problems = []
562 for f in input_api.AffectedFiles():
563 if (not f.LocalPath().endswith(('.cc', '.mm'))):
564 continue
565
566 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04567 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18568 problems.append(' %s:%d' % (f.LocalPath(), line_num))
569
570 if not problems:
571 return []
572 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
573 '\n'.join(problems))]
574
575
danakj61c1aa22015-10-26 19:55:52576def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57577 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52578 errors = []
579 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
580 input_api.re.MULTILINE)
581 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
582 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
583 continue
584 for lnum, line in f.ChangedContents():
585 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17586 errors.append(output_api.PresubmitError(
587 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57588 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17589 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52590 return errors
591
592
mcasasb7440c282015-02-04 14:52:19593def _FindHistogramNameInLine(histogram_name, line):
594 """Tries to find a histogram name or prefix in a line."""
595 if not "affected-histogram" in line:
596 return histogram_name in line
597 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
598 # the histogram_name.
599 if not '"' in line:
600 return False
601 histogram_prefix = line.split('\"')[1]
602 return histogram_prefix in histogram_name
603
604
605def _CheckUmaHistogramChanges(input_api, output_api):
606 """Check that UMA histogram names in touched lines can still be found in other
607 lines of the patch or in histograms.xml. Note that this check would not catch
608 the reverse: changes in histograms.xml not matched in the code itself."""
609 touched_histograms = []
610 histograms_xml_modifications = []
611 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
612 for f in input_api.AffectedFiles():
613 # If histograms.xml itself is modified, keep the modified lines for later.
614 if f.LocalPath().endswith(('histograms.xml')):
615 histograms_xml_modifications = f.ChangedContents()
616 continue
617 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
618 continue
619 for line_num, line in f.ChangedContents():
620 found = pattern.search(line)
621 if found:
622 touched_histograms.append([found.group(1), f, line_num])
623
624 # Search for the touched histogram names in the local modifications to
625 # histograms.xml, and, if not found, on the base histograms.xml file.
626 unmatched_histograms = []
627 for histogram_info in touched_histograms:
628 histogram_name_found = False
629 for line_num, line in histograms_xml_modifications:
630 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
631 if histogram_name_found:
632 break
633 if not histogram_name_found:
634 unmatched_histograms.append(histogram_info)
635
eromanb90c82e7e32015-04-01 15:13:49636 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19637 problems = []
638 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49639 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19640 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45641 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19642 histogram_name_found = False
643 for line in histograms_xml:
644 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
645 if histogram_name_found:
646 break
647 if not histogram_name_found:
648 problems.append(' [%s:%d] %s' %
649 (f.LocalPath(), line_num, histogram_name))
650
651 if not problems:
652 return []
653 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
654 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49655 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19656
wnwenbdc444e2016-05-25 13:44:15657
yolandyandaabc6d2016-04-18 18:29:39658def _CheckFlakyTestUsage(input_api, output_api):
659 """Check that FlakyTest annotation is our own instead of the android one"""
660 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
661 files = []
662 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
663 if f.LocalPath().endswith('Test.java'):
664 if pattern.search(input_api.ReadFile(f)):
665 files.append(f)
666 if len(files):
667 return [output_api.PresubmitError(
668 'Use org.chromium.base.test.util.FlakyTest instead of '
669 'android.test.FlakyTest',
670 files)]
671 return []
mcasasb7440c282015-02-04 14:52:19672
wnwenbdc444e2016-05-25 13:44:15673
[email protected]8ea5d4b2011-09-13 21:49:22674def _CheckNoNewWStrings(input_api, output_api):
675 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27676 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22677 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20678 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57679 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34680 '/win/' in f.LocalPath() or
681 'chrome_elf' in f.LocalPath() or
682 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20683 continue
[email protected]8ea5d4b2011-09-13 21:49:22684
[email protected]a11dbe9b2012-08-07 01:32:58685 allowWString = False
[email protected]b5c24292011-11-28 14:38:20686 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58687 if 'presubmit: allow wstring' in line:
688 allowWString = True
689 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27690 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58691 allowWString = False
692 else:
693 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22694
[email protected]55463aa62011-10-12 00:48:27695 if not problems:
696 return []
697 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58698 ' If you are calling a cross-platform API that accepts a wstring, '
699 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27700 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22701
702
[email protected]2a8ac9c2011-10-19 17:20:44703def _CheckNoDEPSGIT(input_api, output_api):
704 """Make sure .DEPS.git is never modified manually."""
705 if any(f.LocalPath().endswith('.DEPS.git') for f in
706 input_api.AffectedFiles()):
707 return [output_api.PresubmitError(
708 'Never commit changes to .DEPS.git. This file is maintained by an\n'
709 'automated system based on what\'s in DEPS and your changes will be\n'
710 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34711 '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:44712 'for more information')]
713 return []
714
715
tandriief664692014-09-23 14:51:47716def _CheckValidHostsInDEPS(input_api, output_api):
717 """Checks that DEPS file deps are from allowed_hosts."""
718 # Run only if DEPS file has been modified to annoy fewer bystanders.
719 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
720 return []
721 # Outsource work to gclient verify
722 try:
723 input_api.subprocess.check_output(['gclient', 'verify'])
724 return []
725 except input_api.subprocess.CalledProcessError, error:
726 return [output_api.PresubmitError(
727 'DEPS file must have only git dependencies.',
728 long_text=error.output)]
729
730
[email protected]127f18ec2012-06-16 05:05:59731def _CheckNoBannedFunctions(input_api, output_api):
732 """Make sure that banned functions are not used."""
733 warnings = []
734 errors = []
735
wnwenbdc444e2016-05-25 13:44:15736 def IsBlacklisted(affected_file, blacklist):
737 local_path = affected_file.LocalPath()
738 for item in blacklist:
739 if input_api.re.match(item, local_path):
740 return True
741 return False
742
743 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
744 matched = False
745 if func_name[0:1] == '/':
746 regex = func_name[1:]
747 if input_api.re.search(regex, line):
748 matched = True
749 elif func_name in line:
dchenge07de812016-06-20 19:27:17750 matched = True
wnwenbdc444e2016-05-25 13:44:15751 if matched:
dchenge07de812016-06-20 19:27:17752 problems = warnings
wnwenbdc444e2016-05-25 13:44:15753 if error:
dchenge07de812016-06-20 19:27:17754 problems = errors
wnwenbdc444e2016-05-25 13:44:15755 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
756 for message_line in message:
757 problems.append(' %s' % message_line)
758
[email protected]127f18ec2012-06-16 05:05:59759 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
760 for f in input_api.AffectedFiles(file_filter=file_filter):
761 for line_num, line in f.ChangedContents():
762 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15763 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59764
765 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
766 for f in input_api.AffectedFiles(file_filter=file_filter):
767 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49768 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49769 if IsBlacklisted(f, excluded_paths):
770 continue
wnwenbdc444e2016-05-25 13:44:15771 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59772
773 result = []
774 if (warnings):
775 result.append(output_api.PresubmitPromptWarning(
776 'Banned functions were used.\n' + '\n'.join(warnings)))
777 if (errors):
778 result.append(output_api.PresubmitError(
779 'Banned functions were used.\n' + '\n'.join(errors)))
780 return result
781
782
[email protected]6c063c62012-07-11 19:11:06783def _CheckNoPragmaOnce(input_api, output_api):
784 """Make sure that banned functions are not used."""
785 files = []
786 pattern = input_api.re.compile(r'^#pragma\s+once',
787 input_api.re.MULTILINE)
788 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
789 if not f.LocalPath().endswith('.h'):
790 continue
791 contents = input_api.ReadFile(f)
792 if pattern.search(contents):
793 files.append(f)
794
795 if files:
796 return [output_api.PresubmitError(
797 'Do not use #pragma once in header files.\n'
798 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
799 files)]
800 return []
801
[email protected]127f18ec2012-06-16 05:05:59802
[email protected]e7479052012-09-19 00:26:12803def _CheckNoTrinaryTrueFalse(input_api, output_api):
804 """Checks to make sure we don't introduce use of foo ? true : false."""
805 problems = []
806 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
807 for f in input_api.AffectedFiles():
808 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
809 continue
810
811 for line_num, line in f.ChangedContents():
812 if pattern.match(line):
813 problems.append(' %s:%d' % (f.LocalPath(), line_num))
814
815 if not problems:
816 return []
817 return [output_api.PresubmitPromptWarning(
818 'Please consider avoiding the "? true : false" pattern if possible.\n' +
819 '\n'.join(problems))]
820
821
[email protected]55f9f382012-07-31 11:02:18822def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28823 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18824 change. Breaking - rules is an error, breaking ! rules is a
825 warning.
826 """
mohan.reddyf21db962014-10-16 12:26:47827 import sys
[email protected]55f9f382012-07-31 11:02:18828 # We need to wait until we have an input_api object and use this
829 # roundabout construct to import checkdeps because this file is
830 # eval-ed and thus doesn't have __file__.
831 original_sys_path = sys.path
832 try:
833 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47834 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18835 import checkdeps
836 from cpp_checker import CppChecker
rhalavati08acd232017-04-03 07:23:28837 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18838 from rules import Rule
839 finally:
840 # Restore sys.path to what it was before.
841 sys.path = original_sys_path
842
843 added_includes = []
rhalavati08acd232017-04-03 07:23:28844 added_imports = []
[email protected]55f9f382012-07-31 11:02:18845 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28846 if CppChecker.IsCppFile(f.LocalPath()):
847 changed_lines = [line for line_num, line in f.ChangedContents()]
848 added_includes.append([f.LocalPath(), changed_lines])
849 elif ProtoChecker.IsProtoFile(f.LocalPath()):
850 changed_lines = [line for line_num, line in f.ChangedContents()]
851 added_imports.append([f.LocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18852
[email protected]26385172013-05-09 23:11:35853 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18854
855 error_descriptions = []
856 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28857 error_subjects = set()
858 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18859 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
860 added_includes):
861 description_with_path = '%s\n %s' % (path, rule_description)
862 if rule_type == Rule.DISALLOW:
863 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28864 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18865 else:
866 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28867 warning_subjects.add("#includes")
868
869 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
870 added_imports):
871 description_with_path = '%s\n %s' % (path, rule_description)
872 if rule_type == Rule.DISALLOW:
873 error_descriptions.append(description_with_path)
874 error_subjects.add("imports")
875 else:
876 warning_descriptions.append(description_with_path)
877 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18878
879 results = []
880 if error_descriptions:
881 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28882 'You added one or more %s that violate checkdeps rules.'
883 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18884 error_descriptions))
885 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42886 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28887 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18888 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28889 '%s? See relevant DEPS file(s) for details and contacts.' %
890 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18891 warning_descriptions))
892 return results
893
894
[email protected]fbcafe5a2012-08-08 15:31:22895def _CheckFilePermissions(input_api, output_api):
896 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15897 if input_api.platform == 'win32':
898 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29899 checkperms_tool = input_api.os_path.join(
900 input_api.PresubmitLocalPath(),
901 'tools', 'checkperms', 'checkperms.py')
902 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47903 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22904 for f in input_api.AffectedFiles():
905 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11906 try:
907 input_api.subprocess.check_output(args)
908 return []
909 except input_api.subprocess.CalledProcessError as error:
910 return [output_api.PresubmitError(
911 'checkperms.py failed:',
912 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22913
914
robertocn832f5992017-01-04 19:01:30915def _CheckTeamTags(input_api, output_api):
916 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
917 checkteamtags_tool = input_api.os_path.join(
918 input_api.PresubmitLocalPath(),
919 'tools', 'checkteamtags', 'checkteamtags.py')
920 args = [input_api.python_executable, checkteamtags_tool,
921 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22922 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30923 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
924 'OWNERS']
925 try:
926 if files:
927 input_api.subprocess.check_output(args + files)
928 return []
929 except input_api.subprocess.CalledProcessError as error:
930 return [output_api.PresubmitError(
931 'checkteamtags.py failed:',
932 long_text=error.output)]
933
934
[email protected]c8278b32012-10-30 20:35:49935def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
936 """Makes sure we don't include ui/aura/window_property.h
937 in header files.
938 """
939 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
940 errors = []
941 for f in input_api.AffectedFiles():
942 if not f.LocalPath().endswith('.h'):
943 continue
944 for line_num, line in f.ChangedContents():
945 if pattern.match(line):
946 errors.append(' %s:%d' % (f.LocalPath(), line_num))
947
948 results = []
949 if errors:
950 results.append(output_api.PresubmitError(
951 'Header files should not include ui/aura/window_property.h', errors))
952 return results
953
954
[email protected]70ca77752012-11-20 03:45:03955def _CheckForVersionControlConflictsInFile(input_api, f):
956 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
957 errors = []
958 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23959 if f.LocalPath().endswith('.md'):
960 # First-level headers in markdown look a lot like version control
961 # conflict markers. http://daringfireball.net/projects/markdown/basics
962 continue
[email protected]70ca77752012-11-20 03:45:03963 if pattern.match(line):
964 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
965 return errors
966
967
968def _CheckForVersionControlConflicts(input_api, output_api):
969 """Usually this is not intentional and will cause a compile failure."""
970 errors = []
971 for f in input_api.AffectedFiles():
972 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
973
974 results = []
975 if errors:
976 results.append(output_api.PresubmitError(
977 'Version control conflict markers found, please resolve.', errors))
978 return results
979
estadee17314a02017-01-12 16:22:16980def _CheckGoogleSupportAnswerUrl(input_api, output_api):
981 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
982 errors = []
983 for f in input_api.AffectedFiles():
984 for line_num, line in f.ChangedContents():
985 if pattern.search(line):
986 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
987
988 results = []
989 if errors:
990 results.append(output_api.PresubmitPromptWarning(
991 'Found Google support URL addressed by answer number. Please replace with '
992 'a p= identifier instead. See crbug.com/679462\n', errors))
993 return results
994
[email protected]70ca77752012-11-20 03:45:03995
[email protected]06e6d0ff2012-12-11 01:36:44996def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
997 def FilterFile(affected_file):
998 """Filter function for use with input_api.AffectedSourceFiles,
999 below. This filters out everything except non-test files from
1000 top-level directories that generally speaking should not hard-code
1001 service URLs (e.g. src/android_webview/, src/content/ and others).
1002 """
1003 return input_api.FilterSourceFile(
1004 affected_file,
[email protected]78bb39d62012-12-11 15:11:561005 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441006 black_list=(_EXCLUDED_PATHS +
1007 _TEST_CODE_EXCLUDED_PATHS +
1008 input_api.DEFAULT_BLACK_LIST))
1009
reillyi38965732015-11-16 18:27:331010 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1011 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461012 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1013 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441014 problems = [] # items are (filename, line_number, line)
1015 for f in input_api.AffectedSourceFiles(FilterFile):
1016 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461017 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441018 problems.append((f.LocalPath(), line_num, line))
1019
1020 if problems:
[email protected]f7051d52013-04-02 18:31:421021 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441022 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581023 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441024 [' %s:%d: %s' % (
1025 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031026 else:
1027 return []
[email protected]06e6d0ff2012-12-11 01:36:441028
1029
[email protected]d2530012013-01-25 16:39:271030def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1031 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311032 The native_client_sdk directory is excluded because it has auto-generated PNG
1033 files for documentation.
[email protected]d2530012013-01-25 16:39:271034 """
[email protected]d2530012013-01-25 16:39:271035 errors = []
binji0dcdf342014-12-12 18:32:311036 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1037 black_list = (r'^native_client_sdk[\\\/]',)
1038 file_filter = lambda f: input_api.FilterSourceFile(
1039 f, white_list=white_list, black_list=black_list)
1040 for f in input_api.AffectedFiles(include_deletes=False,
1041 file_filter=file_filter):
1042 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271043
1044 results = []
1045 if errors:
1046 results.append(output_api.PresubmitError(
1047 'The name of PNG files should not have abbreviations. \n'
1048 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1049 'Contact [email protected] if you have questions.', errors))
1050 return results
1051
1052
Daniel Cheng4dcdb6b2017-04-13 08:30:171053def _ExtractAddRulesFromParsedDeps(parsed_deps):
1054 """Extract the rules that add dependencies from a parsed DEPS file.
1055
1056 Args:
1057 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1058 add_rules = set()
1059 add_rules.update([
1060 rule[1:] for rule in parsed_deps.get('include_rules', [])
1061 if rule.startswith('+') or rule.startswith('!')
1062 ])
1063 for specific_file, rules in parsed_deps.get('specific_include_rules',
1064 {}).iteritems():
1065 add_rules.update([
1066 rule[1:] for rule in rules
1067 if rule.startswith('+') or rule.startswith('!')
1068 ])
1069 return add_rules
1070
1071
1072def _ParseDeps(contents):
1073 """Simple helper for parsing DEPS files."""
1074 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171075 class _VarImpl:
1076
1077 def __init__(self, local_scope):
1078 self._local_scope = local_scope
1079
1080 def Lookup(self, var_name):
1081 """Implements the Var syntax."""
1082 try:
1083 return self._local_scope['vars'][var_name]
1084 except KeyError:
1085 raise Exception('Var is not defined: %s' % var_name)
1086
1087 local_scope = {}
1088 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171089 'Var': _VarImpl(local_scope).Lookup,
1090 }
1091 exec contents in global_scope, local_scope
1092 return local_scope
1093
1094
1095def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081096 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411097 a set of DEPS entries that we should look up.
1098
1099 For a directory (rather than a specific filename) we fake a path to
1100 a specific filename by adding /DEPS. This is chosen as a file that
1101 will seldom or never be subject to per-file include_rules.
1102 """
[email protected]2b438d62013-11-14 17:54:141103 # We ignore deps entries on auto-generated directories.
1104 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081105
Daniel Cheng4dcdb6b2017-04-13 08:30:171106 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1107 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1108
1109 added_deps = new_deps.difference(old_deps)
1110
[email protected]2b438d62013-11-14 17:54:141111 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171112 for added_dep in added_deps:
1113 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1114 continue
1115 # Assume that a rule that ends in .h is a rule for a specific file.
1116 if added_dep.endswith('.h'):
1117 results.add(added_dep)
1118 else:
1119 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081120 return results
1121
1122
[email protected]e871964c2013-05-13 14:14:551123def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1124 """When a dependency prefixed with + is added to a DEPS file, we
1125 want to make sure that the change is reviewed by an OWNER of the
1126 target file or directory, to avoid layering violations from being
1127 introduced. This check verifies that this happens.
1128 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171129 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241130
1131 file_filter = lambda f: not input_api.re.match(
1132 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1133 for f in input_api.AffectedFiles(include_deletes=False,
1134 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551135 filename = input_api.os_path.basename(f.LocalPath())
1136 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171137 virtual_depended_on_files.update(_CalculateAddedDeps(
1138 input_api.os_path,
1139 '\n'.join(f.OldContents()),
1140 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551141
[email protected]e871964c2013-05-13 14:14:551142 if not virtual_depended_on_files:
1143 return []
1144
1145 if input_api.is_committing:
1146 if input_api.tbr:
1147 return [output_api.PresubmitNotifyResult(
1148 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271149 if input_api.dry_run:
1150 return [output_api.PresubmitNotifyResult(
1151 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551152 if not input_api.change.issue:
1153 return [output_api.PresubmitError(
1154 "DEPS approval by OWNERS check failed: this change has "
1155 "no Rietveld issue number, so we can't check it for approvals.")]
1156 output = output_api.PresubmitError
1157 else:
1158 output = output_api.PresubmitNotifyResult
1159
1160 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501161 owner_email, reviewers = (
1162 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1163 input_api,
1164 owners_db.email_regexp,
1165 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551166
1167 owner_email = owner_email or input_api.change.author_email
1168
[email protected]de4f7d22013-05-23 14:27:461169 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511170 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461171 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551172 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1173 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411174
1175 # We strip the /DEPS part that was added by
1176 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1177 # directory.
1178 def StripDeps(path):
1179 start_deps = path.rfind('/DEPS')
1180 if start_deps != -1:
1181 return path[:start_deps]
1182 else:
1183 return path
1184 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551185 for path in missing_files]
1186
1187 if unapproved_dependencies:
1188 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151189 output('You need LGTM from owners of depends-on paths in DEPS that were '
1190 'modified in this CL:\n %s' %
1191 '\n '.join(sorted(unapproved_dependencies)))]
1192 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1193 output_list.append(output(
1194 'Suggested missing target path OWNERS:\n %s' %
1195 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551196 return output_list
1197
1198 return []
1199
1200
[email protected]85218562013-11-22 07:41:401201def _CheckSpamLogging(input_api, output_api):
1202 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1203 black_list = (_EXCLUDED_PATHS +
1204 _TEST_CODE_EXCLUDED_PATHS +
1205 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501206 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191207 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481208 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461209 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121210 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1211 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581212 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591213 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161214 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031215 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151216 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1217 r"^chromecast[\\\/]",
1218 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481219 r"^components[\\\/]browser_watcher[\\\/]"
1220 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311221 r"^components[\\\/]html_viewer[\\\/]"
1222 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461223 # TODO(peter): Remove this exception. https://crbug.com/534537
1224 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1225 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251226 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1227 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241228 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111229 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151230 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111231 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521232 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501233 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361234 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311235 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131236 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001237 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441238 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451239 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021240 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351241 r"dump_file_system.cc$",
1242 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401243 source_file_filter = lambda x: input_api.FilterSourceFile(
1244 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1245
thomasanderson625d3932017-03-29 07:16:581246 log_info = set([])
1247 printf = set([])
[email protected]85218562013-11-22 07:41:401248
1249 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581250 for _, line in f.ChangedContents():
1251 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1252 log_info.add(f.LocalPath())
1253 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1254 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371255
thomasanderson625d3932017-03-29 07:16:581256 if input_api.re.search(r"\bprintf\(", line):
1257 printf.add(f.LocalPath())
1258 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1259 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401260
1261 if log_info:
1262 return [output_api.PresubmitError(
1263 'These files spam the console log with LOG(INFO):',
1264 items=log_info)]
1265 if printf:
1266 return [output_api.PresubmitError(
1267 'These files spam the console log with printf/fprintf:',
1268 items=printf)]
1269 return []
1270
1271
[email protected]49aa76a2013-12-04 06:59:161272def _CheckForAnonymousVariables(input_api, output_api):
1273 """These types are all expected to hold locks while in scope and
1274 so should never be anonymous (which causes them to be immediately
1275 destroyed)."""
1276 they_who_must_be_named = [
1277 'base::AutoLock',
1278 'base::AutoReset',
1279 'base::AutoUnlock',
1280 'SkAutoAlphaRestore',
1281 'SkAutoBitmapShaderInstall',
1282 'SkAutoBlitterChoose',
1283 'SkAutoBounderCommit',
1284 'SkAutoCallProc',
1285 'SkAutoCanvasRestore',
1286 'SkAutoCommentBlock',
1287 'SkAutoDescriptor',
1288 'SkAutoDisableDirectionCheck',
1289 'SkAutoDisableOvalCheck',
1290 'SkAutoFree',
1291 'SkAutoGlyphCache',
1292 'SkAutoHDC',
1293 'SkAutoLockColors',
1294 'SkAutoLockPixels',
1295 'SkAutoMalloc',
1296 'SkAutoMaskFreeImage',
1297 'SkAutoMutexAcquire',
1298 'SkAutoPathBoundsUpdate',
1299 'SkAutoPDFRelease',
1300 'SkAutoRasterClipValidate',
1301 'SkAutoRef',
1302 'SkAutoTime',
1303 'SkAutoTrace',
1304 'SkAutoUnref',
1305 ]
1306 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1307 # bad: base::AutoLock(lock.get());
1308 # not bad: base::AutoLock lock(lock.get());
1309 bad_pattern = input_api.re.compile(anonymous)
1310 # good: new base::AutoLock(lock.get())
1311 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1312 errors = []
1313
1314 for f in input_api.AffectedFiles():
1315 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1316 continue
1317 for linenum, line in f.ChangedContents():
1318 if bad_pattern.search(line) and not good_pattern.search(line):
1319 errors.append('%s:%d' % (f.LocalPath(), linenum))
1320
1321 if errors:
1322 return [output_api.PresubmitError(
1323 'These lines create anonymous variables that need to be named:',
1324 items=errors)]
1325 return []
1326
1327
[email protected]999261d2014-03-03 20:08:081328def _CheckUserActionUpdate(input_api, output_api):
1329 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521330 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081331 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521332 # If actions.xml is already included in the changelist, the PRESUBMIT
1333 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081334 return []
1335
[email protected]999261d2014-03-03 20:08:081336 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1337 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521338 current_actions = None
[email protected]999261d2014-03-03 20:08:081339 for f in input_api.AffectedFiles(file_filter=file_filter):
1340 for line_num, line in f.ChangedContents():
1341 match = input_api.re.search(action_re, line)
1342 if match:
[email protected]2f92dec2014-03-07 19:21:521343 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1344 # loaded only once.
1345 if not current_actions:
1346 with open('tools/metrics/actions/actions.xml') as actions_f:
1347 current_actions = actions_f.read()
1348 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081349 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521350 action = 'name="{0}"'.format(action_name)
1351 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081352 return [output_api.PresubmitPromptWarning(
1353 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521354 'tools/metrics/actions/actions.xml. Please run '
1355 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081356 % (f.LocalPath(), line_num, action_name))]
1357 return []
1358
1359
Daniel Cheng13ca61a882017-08-25 15:11:251360def _ImportJSONCommentEater(input_api):
1361 import sys
1362 sys.path = sys.path + [input_api.os_path.join(
1363 input_api.PresubmitLocalPath(),
1364 'tools', 'json_comment_eater')]
1365 import json_comment_eater
1366 return json_comment_eater
1367
1368
[email protected]99171a92014-06-03 08:44:471369def _GetJSONParseError(input_api, filename, eat_comments=True):
1370 try:
1371 contents = input_api.ReadFile(filename)
1372 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251373 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131374 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471375
1376 input_api.json.loads(contents)
1377 except ValueError as e:
1378 return e
1379 return None
1380
1381
1382def _GetIDLParseError(input_api, filename):
1383 try:
1384 contents = input_api.ReadFile(filename)
1385 idl_schema = input_api.os_path.join(
1386 input_api.PresubmitLocalPath(),
1387 'tools', 'json_schema_compiler', 'idl_schema.py')
1388 process = input_api.subprocess.Popen(
1389 [input_api.python_executable, idl_schema],
1390 stdin=input_api.subprocess.PIPE,
1391 stdout=input_api.subprocess.PIPE,
1392 stderr=input_api.subprocess.PIPE,
1393 universal_newlines=True)
1394 (_, error) = process.communicate(input=contents)
1395 return error or None
1396 except ValueError as e:
1397 return e
1398
1399
1400def _CheckParseErrors(input_api, output_api):
1401 """Check that IDL and JSON files do not contain syntax errors."""
1402 actions = {
1403 '.idl': _GetIDLParseError,
1404 '.json': _GetJSONParseError,
1405 }
[email protected]99171a92014-06-03 08:44:471406 # Most JSON files are preprocessed and support comments, but these do not.
1407 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491408 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471409 ]
1410 # Only run IDL checker on files in these directories.
1411 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491412 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1413 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471414 ]
1415
1416 def get_action(affected_file):
1417 filename = affected_file.LocalPath()
1418 return actions.get(input_api.os_path.splitext(filename)[1])
1419
[email protected]99171a92014-06-03 08:44:471420 def FilterFile(affected_file):
1421 action = get_action(affected_file)
1422 if not action:
1423 return False
1424 path = affected_file.LocalPath()
1425
Sean Kau46e29bc2017-08-28 16:31:161426 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471427 return False
1428
1429 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161430 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471431 return False
1432 return True
1433
1434 results = []
1435 for affected_file in input_api.AffectedFiles(
1436 file_filter=FilterFile, include_deletes=False):
1437 action = get_action(affected_file)
1438 kwargs = {}
1439 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161440 _MatchesFile(input_api, json_no_comments_patterns,
1441 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471442 kwargs['eat_comments'] = False
1443 parse_error = action(input_api,
1444 affected_file.AbsoluteLocalPath(),
1445 **kwargs)
1446 if parse_error:
1447 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1448 (affected_file.LocalPath(), parse_error)))
1449 return results
1450
1451
[email protected]760deea2013-12-10 19:33:491452def _CheckJavaStyle(input_api, output_api):
1453 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471454 import sys
[email protected]760deea2013-12-10 19:33:491455 original_sys_path = sys.path
1456 try:
1457 sys.path = sys.path + [input_api.os_path.join(
1458 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1459 import checkstyle
1460 finally:
1461 # Restore sys.path to what it was before.
1462 sys.path = original_sys_path
1463
1464 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091465 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511466 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491467
1468
Sean Kau46e29bc2017-08-28 16:31:161469def _MatchesFile(input_api, patterns, path):
1470 for pattern in patterns:
1471 if input_api.re.search(pattern, path):
1472 return True
1473 return False
1474
1475
dchenge07de812016-06-20 19:27:171476def _CheckIpcOwners(input_api, output_api):
1477 """Checks that affected files involving IPC have an IPC OWNERS rule.
1478
1479 Whether or not a file affects IPC is determined by a simple whitelist of
1480 filename patterns."""
1481 file_patterns = [
palmerb19a0932017-01-24 04:00:311482 # Legacy IPC:
dchenge07de812016-06-20 19:27:171483 '*_messages.cc',
1484 '*_messages*.h',
1485 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311486 # Mojo IPC:
dchenge07de812016-06-20 19:27:171487 '*.mojom',
1488 '*_struct_traits*.*',
1489 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311490 '*.typemap',
1491 # Android native IPC:
1492 '*.aidl',
1493 # Blink uses a different file naming convention:
1494 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171495 '*StructTraits*.*',
1496 '*TypeConverter*.*',
1497 ]
1498
scottmg7a6ed5ba2016-11-04 18:22:041499 # These third_party directories do not contain IPCs, but contain files
1500 # matching the above patterns, which trigger false positives.
1501 exclude_paths = [
1502 'third_party/crashpad/*',
1503 ]
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
1629 not f.LocalPath().startswith('third_party/WebKit') and
1630 not f.LocalPath().startswith('third_party\\WebKit')):
1631 continue
1632
jbriance9e12f162016-11-25 07:57:501633 if not f.LocalPath().endswith('.h'):
1634 continue
1635
1636 contents = input_api.ReadFile(f)
1637 fwd_decls = input_api.re.findall(class_pattern, contents)
1638 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1639
1640 useless_fwd_decls = []
1641 for decl in fwd_decls:
1642 count = sum(1 for _ in input_api.re.finditer(
1643 r'\b%s\b' % input_api.re.escape(decl), contents))
1644 if count == 1:
1645 useless_fwd_decls.append(decl)
1646
1647 if not useless_fwd_decls:
1648 continue
1649
1650 for line in f.GenerateScmDiff().splitlines():
1651 if (line.startswith('-') and not line.startswith('--') or
1652 line.startswith('+') and not line.startswith('++')):
1653 for decl in useless_fwd_decls:
1654 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1655 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241656 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501657 (f.LocalPath(), decl)))
1658 useless_fwd_decls.remove(decl)
1659
1660 return results
1661
1662
dskiba88634f4e2015-08-14 23:03:291663def _CheckAndroidToastUsage(input_api, output_api):
1664 """Checks that code uses org.chromium.ui.widget.Toast instead of
1665 android.widget.Toast (Chromium Toast doesn't force hardware
1666 acceleration on low-end devices, saving memory).
1667 """
1668 toast_import_pattern = input_api.re.compile(
1669 r'^import android\.widget\.Toast;$')
1670
1671 errors = []
1672
1673 sources = lambda affected_file: input_api.FilterSourceFile(
1674 affected_file,
1675 black_list=(_EXCLUDED_PATHS +
1676 _TEST_CODE_EXCLUDED_PATHS +
1677 input_api.DEFAULT_BLACK_LIST +
1678 (r'^chromecast[\\\/].*',
1679 r'^remoting[\\\/].*')),
1680 white_list=(r'.*\.java$',))
1681
1682 for f in input_api.AffectedSourceFiles(sources):
1683 for line_num, line in f.ChangedContents():
1684 if toast_import_pattern.search(line):
1685 errors.append("%s:%d" % (f.LocalPath(), line_num))
1686
1687 results = []
1688
1689 if errors:
1690 results.append(output_api.PresubmitError(
1691 'android.widget.Toast usage is detected. Android toasts use hardware'
1692 ' acceleration, and can be\ncostly on low-end devices. Please use'
1693 ' org.chromium.ui.widget.Toast instead.\n'
1694 'Contact [email protected] if you have any questions.',
1695 errors))
1696
1697 return results
1698
1699
dgnaa68d5e2015-06-10 10:08:221700def _CheckAndroidCrLogUsage(input_api, output_api):
1701 """Checks that new logs using org.chromium.base.Log:
1702 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511703 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221704 """
pkotwicza1dd0b002016-05-16 14:41:041705
torne89540622017-03-24 19:41:301706 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041707 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301708 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041709 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301710 # WebView license viewer code cannot depend on //base; used in stub APK.
1711 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1712 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041713 ]
1714
dgnaa68d5e2015-06-10 10:08:221715 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121716 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1717 class_in_base_pattern = input_api.re.compile(
1718 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1719 has_some_log_import_pattern = input_api.re.compile(
1720 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221721 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121722 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221723 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511724 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221725 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221726
Vincent Scheib16d7b272015-09-15 18:09:071727 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221728 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041729 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1730 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121731
dgnaa68d5e2015-06-10 10:08:221732 tag_decl_errors = []
1733 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121734 tag_errors = []
dgn38736db2015-09-18 19:20:511735 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121736 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221737
1738 for f in input_api.AffectedSourceFiles(sources):
1739 file_content = input_api.ReadFile(f)
1740 has_modified_logs = False
1741
1742 # Per line checks
dgn87d9fb62015-06-12 09:15:121743 if (cr_log_import_pattern.search(file_content) or
1744 (class_in_base_pattern.search(file_content) and
1745 not has_some_log_import_pattern.search(file_content))):
1746 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221747 for line_num, line in f.ChangedContents():
1748
1749 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121750 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221751 if match:
1752 has_modified_logs = True
1753
1754 # Make sure it uses "TAG"
1755 if not match.group('tag') == 'TAG':
1756 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121757 else:
1758 # Report non cr Log function calls in changed lines
1759 for line_num, line in f.ChangedContents():
1760 if log_call_pattern.search(line):
1761 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221762
1763 # Per file checks
1764 if has_modified_logs:
1765 # Make sure the tag is using the "cr" prefix and is not too long
1766 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511767 tag_name = match.group('name') if match else None
1768 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221769 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511770 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221771 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511772 elif '.' in tag_name:
1773 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221774
1775 results = []
1776 if tag_decl_errors:
1777 results.append(output_api.PresubmitPromptWarning(
1778 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511779 '"private static final String TAG = "<package tag>".\n'
1780 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221781 tag_decl_errors))
1782
1783 if tag_length_errors:
1784 results.append(output_api.PresubmitError(
1785 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511786 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221787 tag_length_errors))
1788
1789 if tag_errors:
1790 results.append(output_api.PresubmitPromptWarning(
1791 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1792 tag_errors))
1793
dgn87d9fb62015-06-12 09:15:121794 if util_log_errors:
dgn4401aa52015-04-29 16:26:171795 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121796 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1797 util_log_errors))
1798
dgn38736db2015-09-18 19:20:511799 if tag_with_dot_errors:
1800 results.append(output_api.PresubmitPromptWarning(
1801 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1802 tag_with_dot_errors))
1803
dgn4401aa52015-04-29 16:26:171804 return results
1805
1806
Yoland Yanb92fa522017-08-28 17:37:061807def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1808 """Checks that junit.framework.* is no longer used."""
1809 deprecated_junit_framework_pattern = input_api.re.compile(
1810 r'^import junit\.framework\..*;',
1811 input_api.re.MULTILINE)
1812 sources = lambda x: input_api.FilterSourceFile(
1813 x, white_list=(r'.*\.java$',), black_list=None)
1814 errors = []
1815 for f in input_api.AffectedFiles(sources):
1816 for line_num, line in f.ChangedContents():
1817 if deprecated_junit_framework_pattern.search(line):
1818 errors.append("%s:%d" % (f.LocalPath(), line_num))
1819
1820 results = []
1821 if errors:
1822 results.append(output_api.PresubmitError(
1823 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1824 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1825 ' if you have any question.', errors))
1826 return results
1827
1828
1829def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1830 """Checks that if new Java test classes have inheritance.
1831 Either the new test class is JUnit3 test or it is a JUnit4 test class
1832 with a base class, either case is undesirable.
1833 """
1834 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1835
1836 sources = lambda x: input_api.FilterSourceFile(
1837 x, white_list=(r'.*Test\.java$',), black_list=None)
1838 errors = []
1839 for f in input_api.AffectedFiles(sources):
1840 if not f.OldContents():
1841 class_declaration_start_flag = False
1842 for line_num, line in f.ChangedContents():
1843 if class_declaration_pattern.search(line):
1844 class_declaration_start_flag = True
1845 if class_declaration_start_flag and ' extends ' in line:
1846 errors.append('%s:%d' % (f.LocalPath(), line_num))
1847 if '{' in line:
1848 class_declaration_start_flag = False
1849
1850 results = []
1851 if errors:
1852 results.append(output_api.PresubmitPromptWarning(
1853 'The newly created files include Test classes that inherits from base'
1854 ' class. Please do not use inheritance in JUnit4 tests or add new'
1855 ' JUnit3 tests. Contact [email protected] if you have any'
1856 ' questions.', errors))
1857 return results
1858
yolandyan45001472016-12-21 21:12:421859def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1860 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1861 deprecated_annotation_import_pattern = input_api.re.compile(
1862 r'^import android\.test\.suitebuilder\.annotation\..*;',
1863 input_api.re.MULTILINE)
1864 sources = lambda x: input_api.FilterSourceFile(
1865 x, white_list=(r'.*\.java$',), black_list=None)
1866 errors = []
1867 for f in input_api.AffectedFiles(sources):
1868 for line_num, line in f.ChangedContents():
1869 if deprecated_annotation_import_pattern.search(line):
1870 errors.append("%s:%d" % (f.LocalPath(), line_num))
1871
1872 results = []
1873 if errors:
1874 results.append(output_api.PresubmitError(
1875 'Annotations in android.test.suitebuilder.annotation have been'
1876 ' deprecated since API level 24. Please use android.support.test.filters'
1877 ' from //third_party/android_support_test_runner:runner_java instead.'
1878 ' Contact [email protected] if you have any questions.', errors))
1879 return results
1880
1881
agrieve7b6479d82015-10-07 14:24:221882def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1883 """Checks if MDPI assets are placed in a correct directory."""
1884 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1885 ('/res/drawable/' in f.LocalPath() or
1886 '/res/drawable-ldrtl/' in f.LocalPath()))
1887 errors = []
1888 for f in input_api.AffectedFiles(include_deletes=False,
1889 file_filter=file_filter):
1890 errors.append(' %s' % f.LocalPath())
1891
1892 results = []
1893 if errors:
1894 results.append(output_api.PresubmitError(
1895 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1896 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1897 '/res/drawable-ldrtl/.\n'
1898 'Contact [email protected] if you have questions.', errors))
1899 return results
1900
1901
agrievef32bcc72016-04-04 14:57:401902class PydepsChecker(object):
1903 def __init__(self, input_api, pydeps_files):
1904 self._file_cache = {}
1905 self._input_api = input_api
1906 self._pydeps_files = pydeps_files
1907
1908 def _LoadFile(self, path):
1909 """Returns the list of paths within a .pydeps file relative to //."""
1910 if path not in self._file_cache:
1911 with open(path) as f:
1912 self._file_cache[path] = f.read()
1913 return self._file_cache[path]
1914
1915 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1916 """Returns an interable of paths within the .pydep, relativized to //."""
1917 os_path = self._input_api.os_path
1918 pydeps_dir = os_path.dirname(pydeps_path)
1919 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1920 if not l.startswith('*'))
1921 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1922
1923 def _CreateFilesToPydepsMap(self):
1924 """Returns a map of local_path -> list_of_pydeps."""
1925 ret = {}
1926 for pydep_local_path in self._pydeps_files:
1927 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1928 ret.setdefault(path, []).append(pydep_local_path)
1929 return ret
1930
1931 def ComputeAffectedPydeps(self):
1932 """Returns an iterable of .pydeps files that might need regenerating."""
1933 affected_pydeps = set()
1934 file_to_pydeps_map = None
1935 for f in self._input_api.AffectedFiles(include_deletes=True):
1936 local_path = f.LocalPath()
1937 if local_path == 'DEPS':
1938 return self._pydeps_files
1939 elif local_path.endswith('.pydeps'):
1940 if local_path in self._pydeps_files:
1941 affected_pydeps.add(local_path)
1942 elif local_path.endswith('.py'):
1943 if file_to_pydeps_map is None:
1944 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1945 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1946 return affected_pydeps
1947
1948 def DetermineIfStale(self, pydeps_path):
1949 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411950 import difflib
agrievef32bcc72016-04-04 14:57:401951 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1952 cmd = old_pydeps_data[1][1:].strip()
1953 new_pydeps_data = self._input_api.subprocess.check_output(
1954 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411955 old_contents = old_pydeps_data[2:]
1956 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401957 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411958 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401959
1960
1961def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1962 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001963 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281964 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1965 # Mac, so skip it on other platforms.
1966 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001967 return []
agrievef32bcc72016-04-04 14:57:401968 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1969 is_android = input_api.os_path.exists('third_party/android_tools')
1970 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1971 results = []
1972 # First, check for new / deleted .pydeps.
1973 for f in input_api.AffectedFiles(include_deletes=True):
1974 if f.LocalPath().endswith('.pydeps'):
1975 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1976 results.append(output_api.PresubmitError(
1977 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1978 'remove %s' % f.LocalPath()))
1979 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1980 results.append(output_api.PresubmitError(
1981 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1982 'include %s' % f.LocalPath()))
1983
1984 if results:
1985 return results
1986
1987 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1988
1989 for pydep_path in checker.ComputeAffectedPydeps():
1990 try:
phajdan.jr0d9878552016-11-04 10:49:411991 result = checker.DetermineIfStale(pydep_path)
1992 if result:
1993 cmd, diff = result
agrievef32bcc72016-04-04 14:57:401994 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:411995 'File is stale: %s\nDiff (apply to fix):\n%s\n'
1996 'To regenerate, run:\n\n %s' %
1997 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:401998 except input_api.subprocess.CalledProcessError as error:
1999 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2000 long_text=error.output)]
2001
2002 return results
2003
2004
glidere61efad2015-02-18 17:39:432005def _CheckSingletonInHeaders(input_api, output_api):
2006 """Checks to make sure no header files have |Singleton<|."""
2007 def FileFilter(affected_file):
2008 # It's ok for base/memory/singleton.h to have |Singleton<|.
2009 black_list = (_EXCLUDED_PATHS +
2010 input_api.DEFAULT_BLACK_LIST +
2011 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2012 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2013
sergeyu34d21222015-09-16 00:11:442014 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432015 files = []
2016 for f in input_api.AffectedSourceFiles(FileFilter):
2017 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2018 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2019 contents = input_api.ReadFile(f)
2020 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242021 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432022 pattern.search(line)):
2023 files.append(f)
2024 break
2025
2026 if files:
yolandyandaabc6d2016-04-18 18:29:392027 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442028 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432029 'Please move them to an appropriate source file so that the ' +
2030 'template gets instantiated in a single compilation unit.',
2031 files) ]
2032 return []
2033
2034
[email protected]fd20b902014-05-09 02:14:532035_DEPRECATED_CSS = [
2036 # Values
2037 ( "-webkit-box", "flex" ),
2038 ( "-webkit-inline-box", "inline-flex" ),
2039 ( "-webkit-flex", "flex" ),
2040 ( "-webkit-inline-flex", "inline-flex" ),
2041 ( "-webkit-min-content", "min-content" ),
2042 ( "-webkit-max-content", "max-content" ),
2043
2044 # Properties
2045 ( "-webkit-background-clip", "background-clip" ),
2046 ( "-webkit-background-origin", "background-origin" ),
2047 ( "-webkit-background-size", "background-size" ),
2048 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442049 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532050
2051 # Functions
2052 ( "-webkit-gradient", "gradient" ),
2053 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2054 ( "-webkit-linear-gradient", "linear-gradient" ),
2055 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2056 ( "-webkit-radial-gradient", "radial-gradient" ),
2057 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2058]
2059
dbeam1ec68ac2016-12-15 05:22:242060def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532061 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252062 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342063 documentation and iOS CSS for dom distiller
2064 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252065 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532066 results = []
dbeam070cfe62014-10-22 06:44:022067 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252068 black_list = (_EXCLUDED_PATHS +
2069 _TEST_CODE_EXCLUDED_PATHS +
2070 input_api.DEFAULT_BLACK_LIST +
2071 (r"^chrome/common/extensions/docs",
2072 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342073 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442074 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252075 r"^native_client_sdk"))
2076 file_filter = lambda f: input_api.FilterSourceFile(
2077 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532078 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2079 for line_num, line in fpath.ChangedContents():
2080 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022081 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532082 results.append(output_api.PresubmitError(
2083 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2084 (fpath.LocalPath(), line_num, deprecated_value, value)))
2085 return results
2086
mohan.reddyf21db962014-10-16 12:26:472087
dbeam070cfe62014-10-22 06:44:022088_DEPRECATED_JS = [
2089 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2090 ( "__defineGetter__", "Object.defineProperty" ),
2091 ( "__defineSetter__", "Object.defineProperty" ),
2092]
2093
dbeam1ec68ac2016-12-15 05:22:242094def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022095 """Make sure that we don't use deprecated JS in Chrome code."""
2096 results = []
2097 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2098 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2099 input_api.DEFAULT_BLACK_LIST)
2100 file_filter = lambda f: input_api.FilterSourceFile(
2101 f, white_list=file_inclusion_pattern, black_list=black_list)
2102 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2103 for lnum, line in fpath.ChangedContents():
2104 for (deprecated, replacement) in _DEPRECATED_JS:
2105 if deprecated in line:
2106 results.append(output_api.PresubmitError(
2107 "%s:%d: Use of deprecated JS %s, use %s instead" %
2108 (fpath.LocalPath(), lnum, deprecated, replacement)))
2109 return results
2110
dpapadd651231d82017-07-21 02:44:472111def _CheckForRiskyJsArrowFunction(line_number, line):
2112 if ' => ' in line:
2113 return "line %d, is using an => (arrow) function\n %s\n" % (
2114 line_number, line)
2115 return ''
2116
2117def _CheckForRiskyJsConstLet(input_api, line_number, line):
2118 if input_api.re.match('^\s*(const|let)\s', line):
2119 return "line %d, is using const/let keyword\n %s\n" % (
2120 line_number, line)
2121 return ''
dbeam070cfe62014-10-22 06:44:022122
dbeam1ec68ac2016-12-15 05:22:242123def _CheckForRiskyJsFeatures(input_api, output_api):
2124 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002125 # 'ui/webui/resources/cr_components are not allowed on ios'
2126 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572127 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002128 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472129 results = []
dbeam1ec68ac2016-12-15 05:22:242130 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472131 arrow_error_lines = []
2132 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242133 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472134 arrow_error_lines += filter(None, [
2135 _CheckForRiskyJsArrowFunction(lnum, line),
2136 ])
dbeam1ec68ac2016-12-15 05:22:242137
dpapadd651231d82017-07-21 02:44:472138 const_let_error_lines += filter(None, [
2139 _CheckForRiskyJsConstLet(input_api, lnum, line),
2140 ])
dbeam1ec68ac2016-12-15 05:22:242141
dpapadd651231d82017-07-21 02:44:472142 if arrow_error_lines:
2143 arrow_error_lines = map(
2144 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2145 results.append(
2146 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2147"""
2148Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242149%s
2150Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2151https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472152""" % f.LocalPath()
2153 ])))
dbeam1ec68ac2016-12-15 05:22:242154
dpapadd651231d82017-07-21 02:44:472155 if const_let_error_lines:
2156 const_let_error_lines = map(
2157 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2158 results.append(
2159 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2160"""
2161Use of const/let keywords detected in:
2162%s
2163Please ensure your code does not run on iOS9 because const/let is not fully
2164supported.
2165https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2166https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2167""" % f.LocalPath()
2168 ])))
2169
2170 return results
dbeam1ec68ac2016-12-15 05:22:242171
rlanday6802cf632017-05-30 17:48:362172def _CheckForRelativeIncludes(input_api, output_api):
2173 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2174 import sys
2175 original_sys_path = sys.path
2176 try:
2177 sys.path = sys.path + [input_api.os_path.join(
2178 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2179 from cpp_checker import CppChecker
2180 finally:
2181 # Restore sys.path to what it was before.
2182 sys.path = original_sys_path
2183
2184 bad_files = {}
2185 for f in input_api.AffectedFiles(include_deletes=False):
2186 if (f.LocalPath().startswith('third_party') and
2187 not f.LocalPath().startswith('third_party/WebKit') and
2188 not f.LocalPath().startswith('third_party\\WebKit')):
2189 continue
2190
2191 if not CppChecker.IsCppFile(f.LocalPath()):
2192 continue
2193
2194 relative_includes = [line for line_num, line in f.ChangedContents()
2195 if "#include" in line and "../" in line]
2196 if not relative_includes:
2197 continue
2198 bad_files[f.LocalPath()] = relative_includes
2199
2200 if not bad_files:
2201 return []
2202
2203 error_descriptions = []
2204 for file_path, bad_lines in bad_files.iteritems():
2205 error_description = file_path
2206 for line in bad_lines:
2207 error_description += '\n ' + line
2208 error_descriptions.append(error_description)
2209
2210 results = []
2211 results.append(output_api.PresubmitError(
2212 'You added one or more relative #include paths (including "../").\n'
2213 'These shouldn\'t be used because they can be used to include headers\n'
2214 'from code that\'s not correctly specified as a dependency in the\n'
2215 'relevant BUILD.gn file(s).',
2216 error_descriptions))
2217
2218 return results
2219
Takeshi Yoshinoe387aa32017-08-02 13:16:132220
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202221def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2222 if not isinstance(key, ast.Str):
2223 return 'Key at line %d must be a string literal' % key.lineno
2224 if not isinstance(value, ast.Dict):
2225 return 'Value at line %d must be a dict' % value.lineno
2226 if len(value.keys) != 1:
2227 return 'Dict at line %d must have single entry' % value.lineno
2228 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2229 return (
2230 'Entry at line %d must have a string literal \'filepath\' as key' %
2231 value.lineno)
2232 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132233
Takeshi Yoshinoe387aa32017-08-02 13:16:132234
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202235def _CheckWatchlistsEntrySyntax(key, value, ast):
2236 if not isinstance(key, ast.Str):
2237 return 'Key at line %d must be a string literal' % key.lineno
2238 if not isinstance(value, ast.List):
2239 return 'Value at line %d must be a list' % value.lineno
2240 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132241
Takeshi Yoshinoe387aa32017-08-02 13:16:132242
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202243def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2244 mismatch_template = (
2245 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2246 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132247
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202248 i = 0
2249 last_key = ''
2250 while True:
2251 if i >= len(wd_dict.keys):
2252 if i >= len(w_dict.keys):
2253 return None
2254 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2255 elif i >= len(w_dict.keys):
2256 return (
2257 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132258
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202259 wd_key = wd_dict.keys[i]
2260 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132261
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202262 result = _CheckWatchlistDefinitionsEntrySyntax(
2263 wd_key, wd_dict.values[i], ast)
2264 if result is not None:
2265 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132266
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202267 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2268 if result is not None:
2269 return 'Bad entry in WATCHLISTS dict: %s' % result
2270
2271 if wd_key.s != w_key.s:
2272 return mismatch_template % (
2273 '%s at line %d' % (wd_key.s, wd_key.lineno),
2274 '%s at line %d' % (w_key.s, w_key.lineno))
2275
2276 if wd_key.s < last_key:
2277 return (
2278 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2279 (wd_key.lineno, w_key.lineno))
2280 last_key = wd_key.s
2281
2282 i = i + 1
2283
2284
2285def _CheckWATCHLISTSSyntax(expression, ast):
2286 if not isinstance(expression, ast.Expression):
2287 return 'WATCHLISTS file must contain a valid expression'
2288 dictionary = expression.body
2289 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2290 return 'WATCHLISTS file must have single dict with exactly two entries'
2291
2292 first_key = dictionary.keys[0]
2293 first_value = dictionary.values[0]
2294 second_key = dictionary.keys[1]
2295 second_value = dictionary.values[1]
2296
2297 if (not isinstance(first_key, ast.Str) or
2298 first_key.s != 'WATCHLIST_DEFINITIONS' or
2299 not isinstance(first_value, ast.Dict)):
2300 return (
2301 'The first entry of the dict in WATCHLISTS file must be '
2302 'WATCHLIST_DEFINITIONS dict')
2303
2304 if (not isinstance(second_key, ast.Str) or
2305 second_key.s != 'WATCHLISTS' or
2306 not isinstance(second_value, ast.Dict)):
2307 return (
2308 'The second entry of the dict in WATCHLISTS file must be '
2309 'WATCHLISTS dict')
2310
2311 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132312
2313
2314def _CheckWATCHLISTS(input_api, output_api):
2315 for f in input_api.AffectedFiles(include_deletes=False):
2316 if f.LocalPath() == 'WATCHLISTS':
2317 contents = input_api.ReadFile(f, 'r')
2318
2319 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202320 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132321 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202322 # Get an AST tree for it and scan the tree for detailed style checking.
2323 expression = input_api.ast.parse(
2324 contents, filename='WATCHLISTS', mode='eval')
2325 except ValueError as e:
2326 return [output_api.PresubmitError(
2327 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2328 except SyntaxError as e:
2329 return [output_api.PresubmitError(
2330 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2331 except TypeError as e:
2332 return [output_api.PresubmitError(
2333 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132334
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202335 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2336 if result is not None:
2337 return [output_api.PresubmitError(result)]
2338 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132339
2340 return []
2341
2342
dgnaa68d5e2015-06-10 10:08:222343def _AndroidSpecificOnUploadChecks(input_api, output_api):
2344 """Groups checks that target android code."""
2345 results = []
dgnaa68d5e2015-06-10 10:08:222346 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222347 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292348 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062349 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2350 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422351 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222352 return results
2353
2354
[email protected]22c9bd72011-03-27 16:47:392355def _CommonChecks(input_api, output_api):
2356 """Checks common to both upload and commit."""
2357 results = []
2358 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382359 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542360 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582361 results.extend(
2362 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192363 results.extend(
[email protected]760deea2013-12-10 19:33:492364 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542365 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182366 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522367 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222368 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442369 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592370 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062371 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122372 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182373 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222374 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302375 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492376 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032377 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492378 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442379 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272380 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072381 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542382 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442383 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392384 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552385 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042386 results.extend(
2387 input_api.canned_checks.CheckChangeHasNoTabs(
2388 input_api,
2389 output_api,
2390 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402391 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162392 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082393 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242394 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2395 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472396 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042397 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232398 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432399 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402400 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152401 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172402 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502403 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242404 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362405 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132406 results.extend(_CheckWATCHLISTS(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242407
2408 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2409 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2410 input_api, output_api,
2411 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382412 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392413 return results
[email protected]1f7b4172010-01-28 01:17:342414
[email protected]b337cb5b2011-01-23 21:24:052415
[email protected]b8079ae4a2012-12-05 19:56:492416def _CheckPatchFiles(input_api, output_api):
2417 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2418 if f.LocalPath().endswith(('.orig', '.rej'))]
2419 if problems:
2420 return [output_api.PresubmitError(
2421 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032422 else:
2423 return []
[email protected]b8079ae4a2012-12-05 19:56:492424
2425
Kent Tamura5a8755d2017-06-29 23:37:072426def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212427 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2428 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2429 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072430 include_re = input_api.re.compile(
2431 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2432 extension_re = input_api.re.compile(r'\.[a-z]+$')
2433 errors = []
2434 for f in input_api.AffectedFiles():
2435 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2436 continue
2437 found_line_number = None
2438 found_macro = None
2439 for line_num, line in f.ChangedContents():
2440 match = macro_re.search(line)
2441 if match:
2442 found_line_number = line_num
2443 found_macro = match.group(2)
2444 break
2445 if not found_line_number:
2446 continue
2447
2448 found_include = False
2449 for line in f.NewContents():
2450 if include_re.search(line):
2451 found_include = True
2452 break
2453 if found_include:
2454 continue
2455
2456 if not f.LocalPath().endswith('.h'):
2457 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2458 try:
2459 content = input_api.ReadFile(primary_header_path, 'r')
2460 if include_re.search(content):
2461 continue
2462 except IOError:
2463 pass
2464 errors.append('%s:%d %s macro is used without including build/'
2465 'build_config.h.'
2466 % (f.LocalPath(), found_line_number, found_macro))
2467 if errors:
2468 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2469 return []
2470
2471
[email protected]b00342e7f2013-03-26 16:21:542472def _DidYouMeanOSMacro(bad_macro):
2473 try:
2474 return {'A': 'OS_ANDROID',
2475 'B': 'OS_BSD',
2476 'C': 'OS_CHROMEOS',
2477 'F': 'OS_FREEBSD',
2478 'L': 'OS_LINUX',
2479 'M': 'OS_MACOSX',
2480 'N': 'OS_NACL',
2481 'O': 'OS_OPENBSD',
2482 'P': 'OS_POSIX',
2483 'S': 'OS_SOLARIS',
2484 'W': 'OS_WIN'}[bad_macro[3].upper()]
2485 except KeyError:
2486 return ''
2487
2488
2489def _CheckForInvalidOSMacrosInFile(input_api, f):
2490 """Check for sensible looking, totally invalid OS macros."""
2491 preprocessor_statement = input_api.re.compile(r'^\s*#')
2492 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2493 results = []
2494 for lnum, line in f.ChangedContents():
2495 if preprocessor_statement.search(line):
2496 for match in os_macro.finditer(line):
2497 if not match.group(1) in _VALID_OS_MACROS:
2498 good = _DidYouMeanOSMacro(match.group(1))
2499 did_you_mean = ' (did you mean %s?)' % good if good else ''
2500 results.append(' %s:%d %s%s' % (f.LocalPath(),
2501 lnum,
2502 match.group(1),
2503 did_you_mean))
2504 return results
2505
2506
2507def _CheckForInvalidOSMacros(input_api, output_api):
2508 """Check all affected files for invalid OS macros."""
2509 bad_macros = []
2510 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472511 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542512 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2513
2514 if not bad_macros:
2515 return []
2516
2517 return [output_api.PresubmitError(
2518 'Possibly invalid OS macro[s] found. Please fix your code\n'
2519 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2520
lliabraa35bab3932014-10-01 12:16:442521
2522def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2523 """Check all affected files for invalid "if defined" macros."""
2524 ALWAYS_DEFINED_MACROS = (
2525 "TARGET_CPU_PPC",
2526 "TARGET_CPU_PPC64",
2527 "TARGET_CPU_68K",
2528 "TARGET_CPU_X86",
2529 "TARGET_CPU_ARM",
2530 "TARGET_CPU_MIPS",
2531 "TARGET_CPU_SPARC",
2532 "TARGET_CPU_ALPHA",
2533 "TARGET_IPHONE_SIMULATOR",
2534 "TARGET_OS_EMBEDDED",
2535 "TARGET_OS_IPHONE",
2536 "TARGET_OS_MAC",
2537 "TARGET_OS_UNIX",
2538 "TARGET_OS_WIN32",
2539 )
2540 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2541 results = []
2542 for lnum, line in f.ChangedContents():
2543 for match in ifdef_macro.finditer(line):
2544 if match.group(1) in ALWAYS_DEFINED_MACROS:
2545 always_defined = ' %s is always defined. ' % match.group(1)
2546 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2547 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2548 lnum,
2549 always_defined,
2550 did_you_mean))
2551 return results
2552
2553
2554def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2555 """Check all affected files for invalid "if defined" macros."""
2556 bad_macros = []
2557 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212558 if f.LocalPath().startswith('third_party/sqlite/'):
2559 continue
lliabraa35bab3932014-10-01 12:16:442560 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2561 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2562
2563 if not bad_macros:
2564 return []
2565
2566 return [output_api.PresubmitError(
2567 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2568 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2569 bad_macros)]
2570
2571
mlamouria82272622014-09-16 18:45:042572def _CheckForIPCRules(input_api, output_api):
2573 """Check for same IPC rules described in
2574 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2575 """
2576 base_pattern = r'IPC_ENUM_TRAITS\('
2577 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2578 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2579
2580 problems = []
2581 for f in input_api.AffectedSourceFiles(None):
2582 local_path = f.LocalPath()
2583 if not local_path.endswith('.h'):
2584 continue
2585 for line_number, line in f.ChangedContents():
2586 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2587 problems.append(
2588 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2589
2590 if problems:
2591 return [output_api.PresubmitPromptWarning(
2592 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2593 else:
2594 return []
2595
[email protected]b00342e7f2013-03-26 16:21:542596
mostynbb639aca52015-01-07 20:31:232597def _CheckForWindowsLineEndings(input_api, output_api):
2598 """Check source code and known ascii text files for Windows style line
2599 endings.
2600 """
earthdok1b5e0ee2015-03-10 15:19:102601 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232602
2603 file_inclusion_pattern = (
2604 known_text_files,
2605 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2606 )
2607
2608 filter = lambda f: input_api.FilterSourceFile(
2609 f, white_list=file_inclusion_pattern, black_list=None)
2610 files = [f.LocalPath() for f in
2611 input_api.AffectedSourceFiles(filter)]
2612
2613 problems = []
2614
2615 for file in files:
2616 fp = open(file, 'r')
2617 for line in fp:
2618 if line.endswith('\r\n'):
2619 problems.append(file)
2620 break
2621 fp.close()
2622
2623 if problems:
2624 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2625 'these files to contain Windows style line endings?\n' +
2626 '\n'.join(problems))]
2627
2628 return []
2629
2630
pastarmovj89f7ee12016-09-20 14:58:132631def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2632 lint_filters=None, verbose_level=None):
2633 """Checks that all source files use SYSLOG properly."""
2634 syslog_files = []
2635 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562636 for line_number, line in f.ChangedContents():
2637 if 'SYSLOG' in line:
2638 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2639
pastarmovj89f7ee12016-09-20 14:58:132640 if syslog_files:
2641 return [output_api.PresubmitPromptWarning(
2642 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2643 ' calls.\nFiles to check:\n', items=syslog_files)]
2644 return []
2645
2646
[email protected]1f7b4172010-01-28 01:17:342647def CheckChangeOnUpload(input_api, output_api):
2648 results = []
2649 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472650 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282651 results.extend(
jam93a6ee792017-02-08 23:59:222652 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192653 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222654 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132655 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162656 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542657 return results
[email protected]ca8d19842009-02-19 16:33:122658
2659
[email protected]1bfb8322014-04-23 01:02:412660def GetTryServerMasterForBot(bot):
2661 """Returns the Try Server master for the given bot.
2662
[email protected]0bb112362014-07-26 04:38:322663 It tries to guess the master from the bot name, but may still fail
2664 and return None. There is no longer a default master.
2665 """
2666 # Potentially ambiguous bot names are listed explicitly.
2667 master_map = {
tandriie5587792016-07-14 00:34:502668 'chromium_presubmit': 'master.tryserver.chromium.linux',
2669 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412670 }
[email protected]0bb112362014-07-26 04:38:322671 master = master_map.get(bot)
2672 if not master:
wnwen4fbaab82016-05-25 12:54:362673 if 'android' in bot:
tandriie5587792016-07-14 00:34:502674 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362675 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502676 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322677 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502678 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322679 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502680 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322681 return master
[email protected]1bfb8322014-04-23 01:02:412682
2683
[email protected]ca8d19842009-02-19 16:33:122684def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542685 results = []
[email protected]1f7b4172010-01-28 01:17:342686 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542687 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272688 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342689 input_api,
2690 output_api,
[email protected]2fdd1f362013-01-16 03:56:032691 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272692
jam93a6ee792017-02-08 23:59:222693 results.extend(
2694 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542695 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2696 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412697 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2698 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542699 return results