blob: de5d9cbb4226506003910e94c7261043e4b2b04c [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
Kent Tamurae9b3a9ec2017-08-31 02:20:1919 r"^third_party[\\\/](WebKit|blink)[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
vapierb2053f542017-03-09 19:46:1026 r"tools[\\\/]md_browser[\\\/].*\.css$",
ehmaldonado78eee2ed2017-03-28 13:16:5427 # Test pages for WebRTC telemetry tests.
28 r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4029)
[email protected]ca8d1982009-02-19 16:33:1230
wnwenbdc444e2016-05-25 13:44:1531
[email protected]06e6d0ff2012-12-11 01:36:4432# Fragment of a regular expression that matches C++ and Objective-C++
33# implementation files.
34_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
35
wnwenbdc444e2016-05-25 13:44:1536
[email protected]06e6d0ff2012-12-11 01:36:4437# Regular expression that matches code only used for test binaries
38# (best effort).
39_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4940 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4441 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
sdefresne1fccb0a2016-12-19 08:10:5342 r'.+_(api|browser|eg|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1243 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4444 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4945 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0546 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4947 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4748 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4949 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0850 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4951 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4452)
[email protected]ca8d1982009-02-19 16:33:1253
wnwenbdc444e2016-05-25 13:44:1554
[email protected]eea609a2011-11-18 13:10:1255_TEST_ONLY_WARNING = (
56 'You might be calling functions intended only for testing from\n'
57 'production code. It is OK to ignore this warning if you know what\n'
58 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5859 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1260
61
[email protected]cf9b78f2012-11-14 11:40:2862_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4063 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2164 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
65 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2866
wnwenbdc444e2016-05-25 13:44:1567
[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 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57438 ),
439 (
440 r'std::regex',
441 (
442 'Using std::regex adds unnecessary binary size to Chrome. Please use',
443 're2::RE2 instead (crbug/755321)',
444 ),
445 True,
446 (),
dskiba1474c2bfd62017-07-20 02:19:24447 )
[email protected]127f18ec2012-06-16 05:05:59448)
449
wnwenbdc444e2016-05-25 13:44:15450
mlamouria82272622014-09-16 18:45:04451_IPC_ENUM_TRAITS_DEPRECATED = (
452 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
453 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
454
[email protected]127f18ec2012-06-16 05:05:59455
Sean Kau46e29bc2017-08-28 16:31:16456# These paths contain test data and other known invalid JSON files.
457_KNOWN_INVALID_JSON_FILE_PATTERNS = [
458 r'test[\\\/]data[\\\/]',
459 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
460 r'^third_party[\\\/]protobuf[\\\/]',
461]
462
463
[email protected]b00342e7f2013-03-26 16:21:54464_VALID_OS_MACROS = (
465 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08466 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54467 'OS_ANDROID',
468 'OS_BSD',
469 'OS_CAT', # For testing.
470 'OS_CHROMEOS',
471 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37472 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54473 'OS_IOS',
474 'OS_LINUX',
475 'OS_MACOSX',
476 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21477 'OS_NACL_NONSFI',
478 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12479 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54480 'OS_OPENBSD',
481 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37482 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54483 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54484 'OS_WIN',
485)
486
487
agrievef32bcc72016-04-04 14:57:40488_ANDROID_SPECIFIC_PYDEPS_FILES = [
489 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04490 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58491 'build/secondary/third_party/android_platform/'
492 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19493 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40494]
495
wnwenbdc444e2016-05-25 13:44:15496
agrievef32bcc72016-04-04 14:57:40497_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40498]
499
wnwenbdc444e2016-05-25 13:44:15500
agrievef32bcc72016-04-04 14:57:40501_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
502
503
[email protected]55459852011-08-10 15:17:19504def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
505 """Attempts to prevent use of functions intended only for testing in
506 non-testing code. For now this is just a best-effort implementation
507 that ignores header files and may have some false positives. A
508 better implementation would probably need a proper C++ parser.
509 """
510 # We only scan .cc files and the like, as the declaration of
511 # for-testing functions in header files are hard to distinguish from
512 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44513 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19514
jochenc0d4808c2015-07-27 09:25:42515 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19516 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09517 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19518 exclusion_pattern = input_api.re.compile(
519 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
520 base_function_pattern, base_function_pattern))
521
522 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44523 black_list = (_EXCLUDED_PATHS +
524 _TEST_CODE_EXCLUDED_PATHS +
525 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19526 return input_api.FilterSourceFile(
527 affected_file,
528 white_list=(file_inclusion_pattern, ),
529 black_list=black_list)
530
531 problems = []
532 for f in input_api.AffectedSourceFiles(FilterFile):
533 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24534 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03535 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46536 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03537 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19538 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03539 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19540
541 if problems:
[email protected]f7051d52013-04-02 18:31:42542 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03543 else:
544 return []
[email protected]55459852011-08-10 15:17:19545
546
[email protected]10689ca2011-09-02 02:31:54547def _CheckNoIOStreamInHeaders(input_api, output_api):
548 """Checks to make sure no .h files include <iostream>."""
549 files = []
550 pattern = input_api.re.compile(r'^#include\s*<iostream>',
551 input_api.re.MULTILINE)
552 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
553 if not f.LocalPath().endswith('.h'):
554 continue
555 contents = input_api.ReadFile(f)
556 if pattern.search(contents):
557 files.append(f)
558
559 if len(files):
yolandyandaabc6d2016-04-18 18:29:39560 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06561 'Do not #include <iostream> in header files, since it inserts static '
562 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54563 '#include <ostream>. See http://crbug.com/94794',
564 files) ]
565 return []
566
567
[email protected]72df4e782012-06-21 16:28:18568def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52569 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18570 problems = []
571 for f in input_api.AffectedFiles():
572 if (not f.LocalPath().endswith(('.cc', '.mm'))):
573 continue
574
575 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04576 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18577 problems.append(' %s:%d' % (f.LocalPath(), line_num))
578
579 if not problems:
580 return []
581 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
582 '\n'.join(problems))]
583
584
danakj61c1aa22015-10-26 19:55:52585def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57586 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52587 errors = []
588 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
589 input_api.re.MULTILINE)
590 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
591 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
592 continue
593 for lnum, line in f.ChangedContents():
594 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17595 errors.append(output_api.PresubmitError(
596 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57597 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17598 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52599 return errors
600
601
mcasasb7440c282015-02-04 14:52:19602def _FindHistogramNameInLine(histogram_name, line):
603 """Tries to find a histogram name or prefix in a line."""
604 if not "affected-histogram" in line:
605 return histogram_name in line
606 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
607 # the histogram_name.
608 if not '"' in line:
609 return False
610 histogram_prefix = line.split('\"')[1]
611 return histogram_prefix in histogram_name
612
613
614def _CheckUmaHistogramChanges(input_api, output_api):
615 """Check that UMA histogram names in touched lines can still be found in other
616 lines of the patch or in histograms.xml. Note that this check would not catch
617 the reverse: changes in histograms.xml not matched in the code itself."""
618 touched_histograms = []
619 histograms_xml_modifications = []
620 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
621 for f in input_api.AffectedFiles():
622 # If histograms.xml itself is modified, keep the modified lines for later.
623 if f.LocalPath().endswith(('histograms.xml')):
624 histograms_xml_modifications = f.ChangedContents()
625 continue
626 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
627 continue
628 for line_num, line in f.ChangedContents():
629 found = pattern.search(line)
630 if found:
631 touched_histograms.append([found.group(1), f, line_num])
632
633 # Search for the touched histogram names in the local modifications to
634 # histograms.xml, and, if not found, on the base histograms.xml file.
635 unmatched_histograms = []
636 for histogram_info in touched_histograms:
637 histogram_name_found = False
638 for line_num, line in histograms_xml_modifications:
639 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
640 if histogram_name_found:
641 break
642 if not histogram_name_found:
643 unmatched_histograms.append(histogram_info)
644
eromanb90c82e7e32015-04-01 15:13:49645 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19646 problems = []
647 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49648 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19649 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45650 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19651 histogram_name_found = False
652 for line in histograms_xml:
653 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
654 if histogram_name_found:
655 break
656 if not histogram_name_found:
657 problems.append(' [%s:%d] %s' %
658 (f.LocalPath(), line_num, histogram_name))
659
660 if not problems:
661 return []
662 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
663 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49664 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19665
wnwenbdc444e2016-05-25 13:44:15666
yolandyandaabc6d2016-04-18 18:29:39667def _CheckFlakyTestUsage(input_api, output_api):
668 """Check that FlakyTest annotation is our own instead of the android one"""
669 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
670 files = []
671 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
672 if f.LocalPath().endswith('Test.java'):
673 if pattern.search(input_api.ReadFile(f)):
674 files.append(f)
675 if len(files):
676 return [output_api.PresubmitError(
677 'Use org.chromium.base.test.util.FlakyTest instead of '
678 'android.test.FlakyTest',
679 files)]
680 return []
mcasasb7440c282015-02-04 14:52:19681
wnwenbdc444e2016-05-25 13:44:15682
[email protected]8ea5d4b2011-09-13 21:49:22683def _CheckNoNewWStrings(input_api, output_api):
684 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27685 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22686 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20687 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57688 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34689 '/win/' in f.LocalPath() or
690 'chrome_elf' in f.LocalPath() or
691 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20692 continue
[email protected]8ea5d4b2011-09-13 21:49:22693
[email protected]a11dbe9b2012-08-07 01:32:58694 allowWString = False
[email protected]b5c24292011-11-28 14:38:20695 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58696 if 'presubmit: allow wstring' in line:
697 allowWString = True
698 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27699 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58700 allowWString = False
701 else:
702 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22703
[email protected]55463aa62011-10-12 00:48:27704 if not problems:
705 return []
706 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58707 ' If you are calling a cross-platform API that accepts a wstring, '
708 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27709 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22710
711
[email protected]2a8ac9c2011-10-19 17:20:44712def _CheckNoDEPSGIT(input_api, output_api):
713 """Make sure .DEPS.git is never modified manually."""
714 if any(f.LocalPath().endswith('.DEPS.git') for f in
715 input_api.AffectedFiles()):
716 return [output_api.PresubmitError(
717 'Never commit changes to .DEPS.git. This file is maintained by an\n'
718 'automated system based on what\'s in DEPS and your changes will be\n'
719 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34720 '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:44721 'for more information')]
722 return []
723
724
tandriief664692014-09-23 14:51:47725def _CheckValidHostsInDEPS(input_api, output_api):
726 """Checks that DEPS file deps are from allowed_hosts."""
727 # Run only if DEPS file has been modified to annoy fewer bystanders.
728 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
729 return []
730 # Outsource work to gclient verify
731 try:
732 input_api.subprocess.check_output(['gclient', 'verify'])
733 return []
734 except input_api.subprocess.CalledProcessError, error:
735 return [output_api.PresubmitError(
736 'DEPS file must have only git dependencies.',
737 long_text=error.output)]
738
739
[email protected]127f18ec2012-06-16 05:05:59740def _CheckNoBannedFunctions(input_api, output_api):
741 """Make sure that banned functions are not used."""
742 warnings = []
743 errors = []
744
wnwenbdc444e2016-05-25 13:44:15745 def IsBlacklisted(affected_file, blacklist):
746 local_path = affected_file.LocalPath()
747 for item in blacklist:
748 if input_api.re.match(item, local_path):
749 return True
750 return False
751
752 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
753 matched = False
754 if func_name[0:1] == '/':
755 regex = func_name[1:]
756 if input_api.re.search(regex, line):
757 matched = True
758 elif func_name in line:
dchenge07de812016-06-20 19:27:17759 matched = True
wnwenbdc444e2016-05-25 13:44:15760 if matched:
dchenge07de812016-06-20 19:27:17761 problems = warnings
wnwenbdc444e2016-05-25 13:44:15762 if error:
dchenge07de812016-06-20 19:27:17763 problems = errors
wnwenbdc444e2016-05-25 13:44:15764 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
765 for message_line in message:
766 problems.append(' %s' % message_line)
767
[email protected]127f18ec2012-06-16 05:05:59768 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
769 for f in input_api.AffectedFiles(file_filter=file_filter):
770 for line_num, line in f.ChangedContents():
771 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15772 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59773
774 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
775 for f in input_api.AffectedFiles(file_filter=file_filter):
776 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49777 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49778 if IsBlacklisted(f, excluded_paths):
779 continue
wnwenbdc444e2016-05-25 13:44:15780 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59781
782 result = []
783 if (warnings):
784 result.append(output_api.PresubmitPromptWarning(
785 'Banned functions were used.\n' + '\n'.join(warnings)))
786 if (errors):
787 result.append(output_api.PresubmitError(
788 'Banned functions were used.\n' + '\n'.join(errors)))
789 return result
790
791
[email protected]6c063c62012-07-11 19:11:06792def _CheckNoPragmaOnce(input_api, output_api):
793 """Make sure that banned functions are not used."""
794 files = []
795 pattern = input_api.re.compile(r'^#pragma\s+once',
796 input_api.re.MULTILINE)
797 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
798 if not f.LocalPath().endswith('.h'):
799 continue
800 contents = input_api.ReadFile(f)
801 if pattern.search(contents):
802 files.append(f)
803
804 if files:
805 return [output_api.PresubmitError(
806 'Do not use #pragma once in header files.\n'
807 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
808 files)]
809 return []
810
[email protected]127f18ec2012-06-16 05:05:59811
[email protected]e7479052012-09-19 00:26:12812def _CheckNoTrinaryTrueFalse(input_api, output_api):
813 """Checks to make sure we don't introduce use of foo ? true : false."""
814 problems = []
815 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
816 for f in input_api.AffectedFiles():
817 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
818 continue
819
820 for line_num, line in f.ChangedContents():
821 if pattern.match(line):
822 problems.append(' %s:%d' % (f.LocalPath(), line_num))
823
824 if not problems:
825 return []
826 return [output_api.PresubmitPromptWarning(
827 'Please consider avoiding the "? true : false" pattern if possible.\n' +
828 '\n'.join(problems))]
829
830
[email protected]55f9f382012-07-31 11:02:18831def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28832 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18833 change. Breaking - rules is an error, breaking ! rules is a
834 warning.
835 """
mohan.reddyf21db962014-10-16 12:26:47836 import sys
[email protected]55f9f382012-07-31 11:02:18837 # We need to wait until we have an input_api object and use this
838 # roundabout construct to import checkdeps because this file is
839 # eval-ed and thus doesn't have __file__.
840 original_sys_path = sys.path
841 try:
842 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47843 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18844 import checkdeps
845 from cpp_checker import CppChecker
rhalavati08acd232017-04-03 07:23:28846 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18847 from rules import Rule
848 finally:
849 # Restore sys.path to what it was before.
850 sys.path = original_sys_path
851
852 added_includes = []
rhalavati08acd232017-04-03 07:23:28853 added_imports = []
[email protected]55f9f382012-07-31 11:02:18854 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28855 if CppChecker.IsCppFile(f.LocalPath()):
856 changed_lines = [line for line_num, line in f.ChangedContents()]
857 added_includes.append([f.LocalPath(), changed_lines])
858 elif ProtoChecker.IsProtoFile(f.LocalPath()):
859 changed_lines = [line for line_num, line in f.ChangedContents()]
860 added_imports.append([f.LocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18861
[email protected]26385172013-05-09 23:11:35862 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18863
864 error_descriptions = []
865 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28866 error_subjects = set()
867 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18868 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
869 added_includes):
870 description_with_path = '%s\n %s' % (path, rule_description)
871 if rule_type == Rule.DISALLOW:
872 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28873 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18874 else:
875 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28876 warning_subjects.add("#includes")
877
878 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
879 added_imports):
880 description_with_path = '%s\n %s' % (path, rule_description)
881 if rule_type == Rule.DISALLOW:
882 error_descriptions.append(description_with_path)
883 error_subjects.add("imports")
884 else:
885 warning_descriptions.append(description_with_path)
886 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18887
888 results = []
889 if error_descriptions:
890 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28891 'You added one or more %s that violate checkdeps rules.'
892 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18893 error_descriptions))
894 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42895 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28896 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18897 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28898 '%s? See relevant DEPS file(s) for details and contacts.' %
899 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18900 warning_descriptions))
901 return results
902
903
[email protected]fbcafe5a2012-08-08 15:31:22904def _CheckFilePermissions(input_api, output_api):
905 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15906 if input_api.platform == 'win32':
907 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29908 checkperms_tool = input_api.os_path.join(
909 input_api.PresubmitLocalPath(),
910 'tools', 'checkperms', 'checkperms.py')
911 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47912 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22913 for f in input_api.AffectedFiles():
914 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11915 try:
916 input_api.subprocess.check_output(args)
917 return []
918 except input_api.subprocess.CalledProcessError as error:
919 return [output_api.PresubmitError(
920 'checkperms.py failed:',
921 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22922
923
robertocn832f5992017-01-04 19:01:30924def _CheckTeamTags(input_api, output_api):
925 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
926 checkteamtags_tool = input_api.os_path.join(
927 input_api.PresubmitLocalPath(),
928 'tools', 'checkteamtags', 'checkteamtags.py')
929 args = [input_api.python_executable, checkteamtags_tool,
930 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22931 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30932 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
933 'OWNERS']
934 try:
935 if files:
936 input_api.subprocess.check_output(args + files)
937 return []
938 except input_api.subprocess.CalledProcessError as error:
939 return [output_api.PresubmitError(
940 'checkteamtags.py failed:',
941 long_text=error.output)]
942
943
[email protected]c8278b32012-10-30 20:35:49944def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
945 """Makes sure we don't include ui/aura/window_property.h
946 in header files.
947 """
948 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
949 errors = []
950 for f in input_api.AffectedFiles():
951 if not f.LocalPath().endswith('.h'):
952 continue
953 for line_num, line in f.ChangedContents():
954 if pattern.match(line):
955 errors.append(' %s:%d' % (f.LocalPath(), line_num))
956
957 results = []
958 if errors:
959 results.append(output_api.PresubmitError(
960 'Header files should not include ui/aura/window_property.h', errors))
961 return results
962
963
[email protected]70ca77752012-11-20 03:45:03964def _CheckForVersionControlConflictsInFile(input_api, f):
965 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
966 errors = []
967 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23968 if f.LocalPath().endswith('.md'):
969 # First-level headers in markdown look a lot like version control
970 # conflict markers. http://daringfireball.net/projects/markdown/basics
971 continue
[email protected]70ca77752012-11-20 03:45:03972 if pattern.match(line):
973 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
974 return errors
975
976
977def _CheckForVersionControlConflicts(input_api, output_api):
978 """Usually this is not intentional and will cause a compile failure."""
979 errors = []
980 for f in input_api.AffectedFiles():
981 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
982
983 results = []
984 if errors:
985 results.append(output_api.PresubmitError(
986 'Version control conflict markers found, please resolve.', errors))
987 return results
988
estadee17314a02017-01-12 16:22:16989def _CheckGoogleSupportAnswerUrl(input_api, output_api):
990 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
991 errors = []
992 for f in input_api.AffectedFiles():
993 for line_num, line in f.ChangedContents():
994 if pattern.search(line):
995 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
996
997 results = []
998 if errors:
999 results.append(output_api.PresubmitPromptWarning(
1000 'Found Google support URL addressed by answer number. Please replace with '
1001 'a p= identifier instead. See crbug.com/679462\n', errors))
1002 return results
1003
[email protected]70ca77752012-11-20 03:45:031004
[email protected]06e6d0ff2012-12-11 01:36:441005def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1006 def FilterFile(affected_file):
1007 """Filter function for use with input_api.AffectedSourceFiles,
1008 below. This filters out everything except non-test files from
1009 top-level directories that generally speaking should not hard-code
1010 service URLs (e.g. src/android_webview/, src/content/ and others).
1011 """
1012 return input_api.FilterSourceFile(
1013 affected_file,
[email protected]78bb39d62012-12-11 15:11:561014 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441015 black_list=(_EXCLUDED_PATHS +
1016 _TEST_CODE_EXCLUDED_PATHS +
1017 input_api.DEFAULT_BLACK_LIST))
1018
reillyi38965732015-11-16 18:27:331019 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1020 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461021 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1022 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441023 problems = [] # items are (filename, line_number, line)
1024 for f in input_api.AffectedSourceFiles(FilterFile):
1025 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461026 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441027 problems.append((f.LocalPath(), line_num, line))
1028
1029 if problems:
[email protected]f7051d52013-04-02 18:31:421030 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441031 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581032 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441033 [' %s:%d: %s' % (
1034 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031035 else:
1036 return []
[email protected]06e6d0ff2012-12-11 01:36:441037
1038
[email protected]d2530012013-01-25 16:39:271039def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1040 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311041 The native_client_sdk directory is excluded because it has auto-generated PNG
1042 files for documentation.
[email protected]d2530012013-01-25 16:39:271043 """
[email protected]d2530012013-01-25 16:39:271044 errors = []
binji0dcdf342014-12-12 18:32:311045 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1046 black_list = (r'^native_client_sdk[\\\/]',)
1047 file_filter = lambda f: input_api.FilterSourceFile(
1048 f, white_list=white_list, black_list=black_list)
1049 for f in input_api.AffectedFiles(include_deletes=False,
1050 file_filter=file_filter):
1051 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271052
1053 results = []
1054 if errors:
1055 results.append(output_api.PresubmitError(
1056 'The name of PNG files should not have abbreviations. \n'
1057 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1058 'Contact [email protected] if you have questions.', errors))
1059 return results
1060
1061
Daniel Cheng4dcdb6b2017-04-13 08:30:171062def _ExtractAddRulesFromParsedDeps(parsed_deps):
1063 """Extract the rules that add dependencies from a parsed DEPS file.
1064
1065 Args:
1066 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1067 add_rules = set()
1068 add_rules.update([
1069 rule[1:] for rule in parsed_deps.get('include_rules', [])
1070 if rule.startswith('+') or rule.startswith('!')
1071 ])
1072 for specific_file, rules in parsed_deps.get('specific_include_rules',
1073 {}).iteritems():
1074 add_rules.update([
1075 rule[1:] for rule in rules
1076 if rule.startswith('+') or rule.startswith('!')
1077 ])
1078 return add_rules
1079
1080
1081def _ParseDeps(contents):
1082 """Simple helper for parsing DEPS files."""
1083 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171084 class _VarImpl:
1085
1086 def __init__(self, local_scope):
1087 self._local_scope = local_scope
1088
1089 def Lookup(self, var_name):
1090 """Implements the Var syntax."""
1091 try:
1092 return self._local_scope['vars'][var_name]
1093 except KeyError:
1094 raise Exception('Var is not defined: %s' % var_name)
1095
1096 local_scope = {}
1097 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171098 'Var': _VarImpl(local_scope).Lookup,
1099 }
1100 exec contents in global_scope, local_scope
1101 return local_scope
1102
1103
1104def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081105 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411106 a set of DEPS entries that we should look up.
1107
1108 For a directory (rather than a specific filename) we fake a path to
1109 a specific filename by adding /DEPS. This is chosen as a file that
1110 will seldom or never be subject to per-file include_rules.
1111 """
[email protected]2b438d62013-11-14 17:54:141112 # We ignore deps entries on auto-generated directories.
1113 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081114
Daniel Cheng4dcdb6b2017-04-13 08:30:171115 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1116 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1117
1118 added_deps = new_deps.difference(old_deps)
1119
[email protected]2b438d62013-11-14 17:54:141120 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171121 for added_dep in added_deps:
1122 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1123 continue
1124 # Assume that a rule that ends in .h is a rule for a specific file.
1125 if added_dep.endswith('.h'):
1126 results.add(added_dep)
1127 else:
1128 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081129 return results
1130
1131
[email protected]e871964c2013-05-13 14:14:551132def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1133 """When a dependency prefixed with + is added to a DEPS file, we
1134 want to make sure that the change is reviewed by an OWNER of the
1135 target file or directory, to avoid layering violations from being
1136 introduced. This check verifies that this happens.
1137 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171138 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241139
1140 file_filter = lambda f: not input_api.re.match(
Kent Tamurae9b3a9ec2017-08-31 02:20:191141 r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:241142 for f in input_api.AffectedFiles(include_deletes=False,
1143 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551144 filename = input_api.os_path.basename(f.LocalPath())
1145 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171146 virtual_depended_on_files.update(_CalculateAddedDeps(
1147 input_api.os_path,
1148 '\n'.join(f.OldContents()),
1149 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551150
[email protected]e871964c2013-05-13 14:14:551151 if not virtual_depended_on_files:
1152 return []
1153
1154 if input_api.is_committing:
1155 if input_api.tbr:
1156 return [output_api.PresubmitNotifyResult(
1157 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271158 if input_api.dry_run:
1159 return [output_api.PresubmitNotifyResult(
1160 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551161 if not input_api.change.issue:
1162 return [output_api.PresubmitError(
1163 "DEPS approval by OWNERS check failed: this change has "
1164 "no Rietveld issue number, so we can't check it for approvals.")]
1165 output = output_api.PresubmitError
1166 else:
1167 output = output_api.PresubmitNotifyResult
1168
1169 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501170 owner_email, reviewers = (
1171 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1172 input_api,
1173 owners_db.email_regexp,
1174 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551175
1176 owner_email = owner_email or input_api.change.author_email
1177
[email protected]de4f7d22013-05-23 14:27:461178 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511179 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461180 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551181 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1182 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411183
1184 # We strip the /DEPS part that was added by
1185 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1186 # directory.
1187 def StripDeps(path):
1188 start_deps = path.rfind('/DEPS')
1189 if start_deps != -1:
1190 return path[:start_deps]
1191 else:
1192 return path
1193 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551194 for path in missing_files]
1195
1196 if unapproved_dependencies:
1197 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151198 output('You need LGTM from owners of depends-on paths in DEPS that were '
1199 'modified in this CL:\n %s' %
1200 '\n '.join(sorted(unapproved_dependencies)))]
1201 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1202 output_list.append(output(
1203 'Suggested missing target path OWNERS:\n %s' %
1204 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551205 return output_list
1206
1207 return []
1208
1209
[email protected]85218562013-11-22 07:41:401210def _CheckSpamLogging(input_api, output_api):
1211 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1212 black_list = (_EXCLUDED_PATHS +
1213 _TEST_CODE_EXCLUDED_PATHS +
1214 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501215 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191216 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481217 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461218 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121219 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1220 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581221 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591222 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161223 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031224 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151225 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1226 r"^chromecast[\\\/]",
1227 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481228 r"^components[\\\/]browser_watcher[\\\/]"
1229 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311230 r"^components[\\\/]html_viewer[\\\/]"
1231 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461232 # TODO(peter): Remove this exception. https://crbug.com/534537
1233 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1234 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251235 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1236 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241237 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111238 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151239 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111240 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521241 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501242 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361243 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311244 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131245 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001246 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441247 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451248 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021249 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351250 r"dump_file_system.cc$",
1251 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401252 source_file_filter = lambda x: input_api.FilterSourceFile(
1253 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1254
thomasanderson625d3932017-03-29 07:16:581255 log_info = set([])
1256 printf = set([])
[email protected]85218562013-11-22 07:41:401257
1258 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581259 for _, line in f.ChangedContents():
1260 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1261 log_info.add(f.LocalPath())
1262 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1263 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371264
thomasanderson625d3932017-03-29 07:16:581265 if input_api.re.search(r"\bprintf\(", line):
1266 printf.add(f.LocalPath())
1267 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1268 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401269
1270 if log_info:
1271 return [output_api.PresubmitError(
1272 'These files spam the console log with LOG(INFO):',
1273 items=log_info)]
1274 if printf:
1275 return [output_api.PresubmitError(
1276 'These files spam the console log with printf/fprintf:',
1277 items=printf)]
1278 return []
1279
1280
[email protected]49aa76a2013-12-04 06:59:161281def _CheckForAnonymousVariables(input_api, output_api):
1282 """These types are all expected to hold locks while in scope and
1283 so should never be anonymous (which causes them to be immediately
1284 destroyed)."""
1285 they_who_must_be_named = [
1286 'base::AutoLock',
1287 'base::AutoReset',
1288 'base::AutoUnlock',
1289 'SkAutoAlphaRestore',
1290 'SkAutoBitmapShaderInstall',
1291 'SkAutoBlitterChoose',
1292 'SkAutoBounderCommit',
1293 'SkAutoCallProc',
1294 'SkAutoCanvasRestore',
1295 'SkAutoCommentBlock',
1296 'SkAutoDescriptor',
1297 'SkAutoDisableDirectionCheck',
1298 'SkAutoDisableOvalCheck',
1299 'SkAutoFree',
1300 'SkAutoGlyphCache',
1301 'SkAutoHDC',
1302 'SkAutoLockColors',
1303 'SkAutoLockPixels',
1304 'SkAutoMalloc',
1305 'SkAutoMaskFreeImage',
1306 'SkAutoMutexAcquire',
1307 'SkAutoPathBoundsUpdate',
1308 'SkAutoPDFRelease',
1309 'SkAutoRasterClipValidate',
1310 'SkAutoRef',
1311 'SkAutoTime',
1312 'SkAutoTrace',
1313 'SkAutoUnref',
1314 ]
1315 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1316 # bad: base::AutoLock(lock.get());
1317 # not bad: base::AutoLock lock(lock.get());
1318 bad_pattern = input_api.re.compile(anonymous)
1319 # good: new base::AutoLock(lock.get())
1320 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1321 errors = []
1322
1323 for f in input_api.AffectedFiles():
1324 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1325 continue
1326 for linenum, line in f.ChangedContents():
1327 if bad_pattern.search(line) and not good_pattern.search(line):
1328 errors.append('%s:%d' % (f.LocalPath(), linenum))
1329
1330 if errors:
1331 return [output_api.PresubmitError(
1332 'These lines create anonymous variables that need to be named:',
1333 items=errors)]
1334 return []
1335
1336
[email protected]999261d2014-03-03 20:08:081337def _CheckUserActionUpdate(input_api, output_api):
1338 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521339 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081340 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521341 # If actions.xml is already included in the changelist, the PRESUBMIT
1342 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081343 return []
1344
[email protected]999261d2014-03-03 20:08:081345 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1346 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521347 current_actions = None
[email protected]999261d2014-03-03 20:08:081348 for f in input_api.AffectedFiles(file_filter=file_filter):
1349 for line_num, line in f.ChangedContents():
1350 match = input_api.re.search(action_re, line)
1351 if match:
[email protected]2f92dec2014-03-07 19:21:521352 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1353 # loaded only once.
1354 if not current_actions:
1355 with open('tools/metrics/actions/actions.xml') as actions_f:
1356 current_actions = actions_f.read()
1357 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081358 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521359 action = 'name="{0}"'.format(action_name)
1360 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081361 return [output_api.PresubmitPromptWarning(
1362 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521363 'tools/metrics/actions/actions.xml. Please run '
1364 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081365 % (f.LocalPath(), line_num, action_name))]
1366 return []
1367
1368
Daniel Cheng13ca61a882017-08-25 15:11:251369def _ImportJSONCommentEater(input_api):
1370 import sys
1371 sys.path = sys.path + [input_api.os_path.join(
1372 input_api.PresubmitLocalPath(),
1373 'tools', 'json_comment_eater')]
1374 import json_comment_eater
1375 return json_comment_eater
1376
1377
[email protected]99171a92014-06-03 08:44:471378def _GetJSONParseError(input_api, filename, eat_comments=True):
1379 try:
1380 contents = input_api.ReadFile(filename)
1381 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251382 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131383 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471384
1385 input_api.json.loads(contents)
1386 except ValueError as e:
1387 return e
1388 return None
1389
1390
1391def _GetIDLParseError(input_api, filename):
1392 try:
1393 contents = input_api.ReadFile(filename)
1394 idl_schema = input_api.os_path.join(
1395 input_api.PresubmitLocalPath(),
1396 'tools', 'json_schema_compiler', 'idl_schema.py')
1397 process = input_api.subprocess.Popen(
1398 [input_api.python_executable, idl_schema],
1399 stdin=input_api.subprocess.PIPE,
1400 stdout=input_api.subprocess.PIPE,
1401 stderr=input_api.subprocess.PIPE,
1402 universal_newlines=True)
1403 (_, error) = process.communicate(input=contents)
1404 return error or None
1405 except ValueError as e:
1406 return e
1407
1408
1409def _CheckParseErrors(input_api, output_api):
1410 """Check that IDL and JSON files do not contain syntax errors."""
1411 actions = {
1412 '.idl': _GetIDLParseError,
1413 '.json': _GetJSONParseError,
1414 }
[email protected]99171a92014-06-03 08:44:471415 # Most JSON files are preprocessed and support comments, but these do not.
1416 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491417 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471418 ]
1419 # Only run IDL checker on files in these directories.
1420 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491421 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1422 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471423 ]
1424
1425 def get_action(affected_file):
1426 filename = affected_file.LocalPath()
1427 return actions.get(input_api.os_path.splitext(filename)[1])
1428
[email protected]99171a92014-06-03 08:44:471429 def FilterFile(affected_file):
1430 action = get_action(affected_file)
1431 if not action:
1432 return False
1433 path = affected_file.LocalPath()
1434
Sean Kau46e29bc2017-08-28 16:31:161435 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471436 return False
1437
1438 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161439 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471440 return False
1441 return True
1442
1443 results = []
1444 for affected_file in input_api.AffectedFiles(
1445 file_filter=FilterFile, include_deletes=False):
1446 action = get_action(affected_file)
1447 kwargs = {}
1448 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161449 _MatchesFile(input_api, json_no_comments_patterns,
1450 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471451 kwargs['eat_comments'] = False
1452 parse_error = action(input_api,
1453 affected_file.AbsoluteLocalPath(),
1454 **kwargs)
1455 if parse_error:
1456 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1457 (affected_file.LocalPath(), parse_error)))
1458 return results
1459
1460
[email protected]760deea2013-12-10 19:33:491461def _CheckJavaStyle(input_api, output_api):
1462 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471463 import sys
[email protected]760deea2013-12-10 19:33:491464 original_sys_path = sys.path
1465 try:
1466 sys.path = sys.path + [input_api.os_path.join(
1467 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1468 import checkstyle
1469 finally:
1470 # Restore sys.path to what it was before.
1471 sys.path = original_sys_path
1472
1473 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091474 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511475 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491476
1477
Sean Kau46e29bc2017-08-28 16:31:161478def _MatchesFile(input_api, patterns, path):
1479 for pattern in patterns:
1480 if input_api.re.search(pattern, path):
1481 return True
1482 return False
1483
1484
dchenge07de812016-06-20 19:27:171485def _CheckIpcOwners(input_api, output_api):
1486 """Checks that affected files involving IPC have an IPC OWNERS rule.
1487
1488 Whether or not a file affects IPC is determined by a simple whitelist of
1489 filename patterns."""
1490 file_patterns = [
palmerb19a0932017-01-24 04:00:311491 # Legacy IPC:
dchenge07de812016-06-20 19:27:171492 '*_messages.cc',
1493 '*_messages*.h',
1494 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311495 # Mojo IPC:
dchenge07de812016-06-20 19:27:171496 '*.mojom',
1497 '*_struct_traits*.*',
1498 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311499 '*.typemap',
1500 # Android native IPC:
1501 '*.aidl',
1502 # Blink uses a different file naming convention:
1503 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171504 '*StructTraits*.*',
1505 '*TypeConverter*.*',
1506 ]
1507
scottmg7a6ed5ba2016-11-04 18:22:041508 # These third_party directories do not contain IPCs, but contain files
1509 # matching the above patterns, which trigger false positives.
1510 exclude_paths = [
1511 'third_party/crashpad/*',
1512 ]
1513
dchenge07de812016-06-20 19:27:171514 # Dictionary mapping an OWNERS file path to Patterns.
1515 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1516 # rules ) to a PatternEntry.
1517 # PatternEntry is a dictionary with two keys:
1518 # - 'files': the files that are matched by this pattern
1519 # - 'rules': the per-file rules needed for this pattern
1520 # For example, if we expect OWNERS file to contain rules for *.mojom and
1521 # *_struct_traits*.*, Patterns might look like this:
1522 # {
1523 # '*.mojom': {
1524 # 'files': ...,
1525 # 'rules': [
1526 # 'per-file *.mojom=set noparent',
1527 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1528 # ],
1529 # },
1530 # '*_struct_traits*.*': {
1531 # 'files': ...,
1532 # 'rules': [
1533 # 'per-file *_struct_traits*.*=set noparent',
1534 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1535 # ],
1536 # },
1537 # }
1538 to_check = {}
1539
Daniel Cheng13ca61a882017-08-25 15:11:251540 def AddPatternToCheck(input_file, pattern):
1541 owners_file = input_api.os_path.join(
1542 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1543 if owners_file not in to_check:
1544 to_check[owners_file] = {}
1545 if pattern not in to_check[owners_file]:
1546 to_check[owners_file][pattern] = {
1547 'files': [],
1548 'rules': [
1549 'per-file %s=set noparent' % pattern,
1550 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1551 ]
1552 }
1553 to_check[owners_file][pattern]['files'].append(f)
1554
dchenge07de812016-06-20 19:27:171555 # Iterate through the affected files to see what we actually need to check
1556 # for. We should only nag patch authors about per-file rules if a file in that
1557 # directory would match that pattern. If a directory only contains *.mojom
1558 # files and no *_messages*.h files, we should only nag about rules for
1559 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251560 for f in input_api.AffectedFiles(include_deletes=False):
1561 # Manifest files don't have a strong naming convention. Instead, scan
1562 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161563 if (f.LocalPath().endswith('.json') and
1564 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1565 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251566 json_comment_eater = _ImportJSONCommentEater(input_api)
1567 mostly_json_lines = '\n'.join(f.NewContents())
1568 # Comments aren't allowed in strict JSON, so filter them out.
1569 json_lines = json_comment_eater.Nom(mostly_json_lines)
1570 json_content = input_api.json.loads(json_lines)
1571 if 'interface_provider_specs' in json_content:
1572 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171573 for pattern in file_patterns:
1574 if input_api.fnmatch.fnmatch(
1575 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041576 skip = False
1577 for exclude in exclude_paths:
1578 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1579 skip = True
1580 break
1581 if skip:
1582 continue
Daniel Cheng13ca61a882017-08-25 15:11:251583 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171584 break
1585
1586 # Now go through the OWNERS files we collected, filtering out rules that are
1587 # already present in that OWNERS file.
1588 for owners_file, patterns in to_check.iteritems():
1589 try:
1590 with file(owners_file) as f:
1591 lines = set(f.read().splitlines())
1592 for entry in patterns.itervalues():
1593 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1594 ]
1595 except IOError:
1596 # No OWNERS file, so all the rules are definitely missing.
1597 continue
1598
1599 # All the remaining lines weren't found in OWNERS files, so emit an error.
1600 errors = []
1601 for owners_file, patterns in to_check.iteritems():
1602 missing_lines = []
1603 files = []
1604 for pattern, entry in patterns.iteritems():
1605 missing_lines.extend(entry['rules'])
1606 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1607 if missing_lines:
1608 errors.append(
Daniel Cheng52111692017-06-14 08:00:591609 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171610 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1611
1612 results = []
1613 if errors:
vabrf5ce3bf92016-07-11 14:52:411614 if input_api.is_committing:
1615 output = output_api.PresubmitError
1616 else:
1617 output = output_api.PresubmitPromptWarning
1618 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591619 'Found OWNERS files that need to be updated for IPC security ' +
1620 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171621 long_text='\n\n'.join(errors)))
1622
1623 return results
1624
1625
jbriance9e12f162016-11-25 07:57:501626def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311627 """Checks that added or removed lines in non third party affected
1628 header files do not lead to new useless class or struct forward
1629 declaration.
jbriance9e12f162016-11-25 07:57:501630 """
1631 results = []
1632 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1633 input_api.re.MULTILINE)
1634 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1635 input_api.re.MULTILINE)
1636 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311637 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:191638 not f.LocalPath().startswith('third_party/blink') and
1639 not f.LocalPath().startswith('third_party\\blink') and
jbriance2c51e821a2016-12-12 08:24:311640 not f.LocalPath().startswith('third_party/WebKit') and
1641 not f.LocalPath().startswith('third_party\\WebKit')):
1642 continue
1643
jbriance9e12f162016-11-25 07:57:501644 if not f.LocalPath().endswith('.h'):
1645 continue
1646
1647 contents = input_api.ReadFile(f)
1648 fwd_decls = input_api.re.findall(class_pattern, contents)
1649 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1650
1651 useless_fwd_decls = []
1652 for decl in fwd_decls:
1653 count = sum(1 for _ in input_api.re.finditer(
1654 r'\b%s\b' % input_api.re.escape(decl), contents))
1655 if count == 1:
1656 useless_fwd_decls.append(decl)
1657
1658 if not useless_fwd_decls:
1659 continue
1660
1661 for line in f.GenerateScmDiff().splitlines():
1662 if (line.startswith('-') and not line.startswith('--') or
1663 line.startswith('+') and not line.startswith('++')):
1664 for decl in useless_fwd_decls:
1665 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1666 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241667 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501668 (f.LocalPath(), decl)))
1669 useless_fwd_decls.remove(decl)
1670
1671 return results
1672
1673
dskiba88634f4e2015-08-14 23:03:291674def _CheckAndroidToastUsage(input_api, output_api):
1675 """Checks that code uses org.chromium.ui.widget.Toast instead of
1676 android.widget.Toast (Chromium Toast doesn't force hardware
1677 acceleration on low-end devices, saving memory).
1678 """
1679 toast_import_pattern = input_api.re.compile(
1680 r'^import android\.widget\.Toast;$')
1681
1682 errors = []
1683
1684 sources = lambda affected_file: input_api.FilterSourceFile(
1685 affected_file,
1686 black_list=(_EXCLUDED_PATHS +
1687 _TEST_CODE_EXCLUDED_PATHS +
1688 input_api.DEFAULT_BLACK_LIST +
1689 (r'^chromecast[\\\/].*',
1690 r'^remoting[\\\/].*')),
1691 white_list=(r'.*\.java$',))
1692
1693 for f in input_api.AffectedSourceFiles(sources):
1694 for line_num, line in f.ChangedContents():
1695 if toast_import_pattern.search(line):
1696 errors.append("%s:%d" % (f.LocalPath(), line_num))
1697
1698 results = []
1699
1700 if errors:
1701 results.append(output_api.PresubmitError(
1702 'android.widget.Toast usage is detected. Android toasts use hardware'
1703 ' acceleration, and can be\ncostly on low-end devices. Please use'
1704 ' org.chromium.ui.widget.Toast instead.\n'
1705 'Contact [email protected] if you have any questions.',
1706 errors))
1707
1708 return results
1709
1710
dgnaa68d5e2015-06-10 10:08:221711def _CheckAndroidCrLogUsage(input_api, output_api):
1712 """Checks that new logs using org.chromium.base.Log:
1713 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511714 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221715 """
pkotwicza1dd0b002016-05-16 14:41:041716
torne89540622017-03-24 19:41:301717 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041718 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301719 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041720 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301721 # WebView license viewer code cannot depend on //base; used in stub APK.
1722 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1723 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041724 ]
1725
dgnaa68d5e2015-06-10 10:08:221726 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121727 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1728 class_in_base_pattern = input_api.re.compile(
1729 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1730 has_some_log_import_pattern = input_api.re.compile(
1731 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221732 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121733 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221734 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511735 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221736 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221737
Vincent Scheib16d7b272015-09-15 18:09:071738 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221739 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041740 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1741 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121742
dgnaa68d5e2015-06-10 10:08:221743 tag_decl_errors = []
1744 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121745 tag_errors = []
dgn38736db2015-09-18 19:20:511746 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121747 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221748
1749 for f in input_api.AffectedSourceFiles(sources):
1750 file_content = input_api.ReadFile(f)
1751 has_modified_logs = False
1752
1753 # Per line checks
dgn87d9fb62015-06-12 09:15:121754 if (cr_log_import_pattern.search(file_content) or
1755 (class_in_base_pattern.search(file_content) and
1756 not has_some_log_import_pattern.search(file_content))):
1757 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221758 for line_num, line in f.ChangedContents():
1759
1760 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121761 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221762 if match:
1763 has_modified_logs = True
1764
1765 # Make sure it uses "TAG"
1766 if not match.group('tag') == 'TAG':
1767 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121768 else:
1769 # Report non cr Log function calls in changed lines
1770 for line_num, line in f.ChangedContents():
1771 if log_call_pattern.search(line):
1772 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221773
1774 # Per file checks
1775 if has_modified_logs:
1776 # Make sure the tag is using the "cr" prefix and is not too long
1777 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511778 tag_name = match.group('name') if match else None
1779 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221780 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511781 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221782 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511783 elif '.' in tag_name:
1784 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221785
1786 results = []
1787 if tag_decl_errors:
1788 results.append(output_api.PresubmitPromptWarning(
1789 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511790 '"private static final String TAG = "<package tag>".\n'
1791 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221792 tag_decl_errors))
1793
1794 if tag_length_errors:
1795 results.append(output_api.PresubmitError(
1796 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511797 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221798 tag_length_errors))
1799
1800 if tag_errors:
1801 results.append(output_api.PresubmitPromptWarning(
1802 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1803 tag_errors))
1804
dgn87d9fb62015-06-12 09:15:121805 if util_log_errors:
dgn4401aa52015-04-29 16:26:171806 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121807 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1808 util_log_errors))
1809
dgn38736db2015-09-18 19:20:511810 if tag_with_dot_errors:
1811 results.append(output_api.PresubmitPromptWarning(
1812 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1813 tag_with_dot_errors))
1814
dgn4401aa52015-04-29 16:26:171815 return results
1816
1817
Yoland Yanb92fa522017-08-28 17:37:061818def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1819 """Checks that junit.framework.* is no longer used."""
1820 deprecated_junit_framework_pattern = input_api.re.compile(
1821 r'^import junit\.framework\..*;',
1822 input_api.re.MULTILINE)
1823 sources = lambda x: input_api.FilterSourceFile(
1824 x, white_list=(r'.*\.java$',), black_list=None)
1825 errors = []
1826 for f in input_api.AffectedFiles(sources):
1827 for line_num, line in f.ChangedContents():
1828 if deprecated_junit_framework_pattern.search(line):
1829 errors.append("%s:%d" % (f.LocalPath(), line_num))
1830
1831 results = []
1832 if errors:
1833 results.append(output_api.PresubmitError(
1834 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1835 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1836 ' if you have any question.', errors))
1837 return results
1838
1839
1840def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1841 """Checks that if new Java test classes have inheritance.
1842 Either the new test class is JUnit3 test or it is a JUnit4 test class
1843 with a base class, either case is undesirable.
1844 """
1845 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1846
1847 sources = lambda x: input_api.FilterSourceFile(
1848 x, white_list=(r'.*Test\.java$',), black_list=None)
1849 errors = []
1850 for f in input_api.AffectedFiles(sources):
1851 if not f.OldContents():
1852 class_declaration_start_flag = False
1853 for line_num, line in f.ChangedContents():
1854 if class_declaration_pattern.search(line):
1855 class_declaration_start_flag = True
1856 if class_declaration_start_flag and ' extends ' in line:
1857 errors.append('%s:%d' % (f.LocalPath(), line_num))
1858 if '{' in line:
1859 class_declaration_start_flag = False
1860
1861 results = []
1862 if errors:
1863 results.append(output_api.PresubmitPromptWarning(
1864 'The newly created files include Test classes that inherits from base'
1865 ' class. Please do not use inheritance in JUnit4 tests or add new'
1866 ' JUnit3 tests. Contact [email protected] if you have any'
1867 ' questions.', errors))
1868 return results
1869
yolandyan45001472016-12-21 21:12:421870def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1871 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1872 deprecated_annotation_import_pattern = input_api.re.compile(
1873 r'^import android\.test\.suitebuilder\.annotation\..*;',
1874 input_api.re.MULTILINE)
1875 sources = lambda x: input_api.FilterSourceFile(
1876 x, white_list=(r'.*\.java$',), black_list=None)
1877 errors = []
1878 for f in input_api.AffectedFiles(sources):
1879 for line_num, line in f.ChangedContents():
1880 if deprecated_annotation_import_pattern.search(line):
1881 errors.append("%s:%d" % (f.LocalPath(), line_num))
1882
1883 results = []
1884 if errors:
1885 results.append(output_api.PresubmitError(
1886 'Annotations in android.test.suitebuilder.annotation have been'
1887 ' deprecated since API level 24. Please use android.support.test.filters'
1888 ' from //third_party/android_support_test_runner:runner_java instead.'
1889 ' Contact [email protected] if you have any questions.', errors))
1890 return results
1891
1892
agrieve7b6479d82015-10-07 14:24:221893def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1894 """Checks if MDPI assets are placed in a correct directory."""
1895 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1896 ('/res/drawable/' in f.LocalPath() or
1897 '/res/drawable-ldrtl/' in f.LocalPath()))
1898 errors = []
1899 for f in input_api.AffectedFiles(include_deletes=False,
1900 file_filter=file_filter):
1901 errors.append(' %s' % f.LocalPath())
1902
1903 results = []
1904 if errors:
1905 results.append(output_api.PresubmitError(
1906 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1907 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1908 '/res/drawable-ldrtl/.\n'
1909 'Contact [email protected] if you have questions.', errors))
1910 return results
1911
1912
agrievef32bcc72016-04-04 14:57:401913class PydepsChecker(object):
1914 def __init__(self, input_api, pydeps_files):
1915 self._file_cache = {}
1916 self._input_api = input_api
1917 self._pydeps_files = pydeps_files
1918
1919 def _LoadFile(self, path):
1920 """Returns the list of paths within a .pydeps file relative to //."""
1921 if path not in self._file_cache:
1922 with open(path) as f:
1923 self._file_cache[path] = f.read()
1924 return self._file_cache[path]
1925
1926 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1927 """Returns an interable of paths within the .pydep, relativized to //."""
1928 os_path = self._input_api.os_path
1929 pydeps_dir = os_path.dirname(pydeps_path)
1930 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1931 if not l.startswith('*'))
1932 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1933
1934 def _CreateFilesToPydepsMap(self):
1935 """Returns a map of local_path -> list_of_pydeps."""
1936 ret = {}
1937 for pydep_local_path in self._pydeps_files:
1938 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1939 ret.setdefault(path, []).append(pydep_local_path)
1940 return ret
1941
1942 def ComputeAffectedPydeps(self):
1943 """Returns an iterable of .pydeps files that might need regenerating."""
1944 affected_pydeps = set()
1945 file_to_pydeps_map = None
1946 for f in self._input_api.AffectedFiles(include_deletes=True):
1947 local_path = f.LocalPath()
1948 if local_path == 'DEPS':
1949 return self._pydeps_files
1950 elif local_path.endswith('.pydeps'):
1951 if local_path in self._pydeps_files:
1952 affected_pydeps.add(local_path)
1953 elif local_path.endswith('.py'):
1954 if file_to_pydeps_map is None:
1955 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1956 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1957 return affected_pydeps
1958
1959 def DetermineIfStale(self, pydeps_path):
1960 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411961 import difflib
agrievef32bcc72016-04-04 14:57:401962 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1963 cmd = old_pydeps_data[1][1:].strip()
1964 new_pydeps_data = self._input_api.subprocess.check_output(
1965 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411966 old_contents = old_pydeps_data[2:]
1967 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401968 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411969 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401970
1971
1972def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1973 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001974 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281975 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1976 # Mac, so skip it on other platforms.
1977 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001978 return []
agrievef32bcc72016-04-04 14:57:401979 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1980 is_android = input_api.os_path.exists('third_party/android_tools')
1981 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1982 results = []
1983 # First, check for new / deleted .pydeps.
1984 for f in input_api.AffectedFiles(include_deletes=True):
1985 if f.LocalPath().endswith('.pydeps'):
1986 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1987 results.append(output_api.PresubmitError(
1988 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1989 'remove %s' % f.LocalPath()))
1990 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1991 results.append(output_api.PresubmitError(
1992 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1993 'include %s' % f.LocalPath()))
1994
1995 if results:
1996 return results
1997
1998 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1999
2000 for pydep_path in checker.ComputeAffectedPydeps():
2001 try:
phajdan.jr0d9878552016-11-04 10:49:412002 result = checker.DetermineIfStale(pydep_path)
2003 if result:
2004 cmd, diff = result
agrievef32bcc72016-04-04 14:57:402005 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:412006 'File is stale: %s\nDiff (apply to fix):\n%s\n'
2007 'To regenerate, run:\n\n %s' %
2008 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:402009 except input_api.subprocess.CalledProcessError as error:
2010 return [output_api.PresubmitError('Error running: %s' % error.cmd,
2011 long_text=error.output)]
2012
2013 return results
2014
2015
glidere61efad2015-02-18 17:39:432016def _CheckSingletonInHeaders(input_api, output_api):
2017 """Checks to make sure no header files have |Singleton<|."""
2018 def FileFilter(affected_file):
2019 # It's ok for base/memory/singleton.h to have |Singleton<|.
2020 black_list = (_EXCLUDED_PATHS +
2021 input_api.DEFAULT_BLACK_LIST +
2022 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2023 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2024
sergeyu34d21222015-09-16 00:11:442025 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432026 files = []
2027 for f in input_api.AffectedSourceFiles(FileFilter):
2028 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2029 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2030 contents = input_api.ReadFile(f)
2031 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242032 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432033 pattern.search(line)):
2034 files.append(f)
2035 break
2036
2037 if files:
yolandyandaabc6d2016-04-18 18:29:392038 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442039 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432040 'Please move them to an appropriate source file so that the ' +
2041 'template gets instantiated in a single compilation unit.',
2042 files) ]
2043 return []
2044
2045
[email protected]fd20b902014-05-09 02:14:532046_DEPRECATED_CSS = [
2047 # Values
2048 ( "-webkit-box", "flex" ),
2049 ( "-webkit-inline-box", "inline-flex" ),
2050 ( "-webkit-flex", "flex" ),
2051 ( "-webkit-inline-flex", "inline-flex" ),
2052 ( "-webkit-min-content", "min-content" ),
2053 ( "-webkit-max-content", "max-content" ),
2054
2055 # Properties
2056 ( "-webkit-background-clip", "background-clip" ),
2057 ( "-webkit-background-origin", "background-origin" ),
2058 ( "-webkit-background-size", "background-size" ),
2059 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442060 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532061
2062 # Functions
2063 ( "-webkit-gradient", "gradient" ),
2064 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2065 ( "-webkit-linear-gradient", "linear-gradient" ),
2066 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2067 ( "-webkit-radial-gradient", "radial-gradient" ),
2068 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2069]
2070
dbeam1ec68ac2016-12-15 05:22:242071def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532072 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252073 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342074 documentation and iOS CSS for dom distiller
2075 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252076 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532077 results = []
dbeam070cfe62014-10-22 06:44:022078 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252079 black_list = (_EXCLUDED_PATHS +
2080 _TEST_CODE_EXCLUDED_PATHS +
2081 input_api.DEFAULT_BLACK_LIST +
2082 (r"^chrome/common/extensions/docs",
2083 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342084 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442085 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252086 r"^native_client_sdk"))
2087 file_filter = lambda f: input_api.FilterSourceFile(
2088 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532089 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2090 for line_num, line in fpath.ChangedContents():
2091 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022092 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532093 results.append(output_api.PresubmitError(
2094 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2095 (fpath.LocalPath(), line_num, deprecated_value, value)))
2096 return results
2097
mohan.reddyf21db962014-10-16 12:26:472098
dbeam070cfe62014-10-22 06:44:022099_DEPRECATED_JS = [
2100 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2101 ( "__defineGetter__", "Object.defineProperty" ),
2102 ( "__defineSetter__", "Object.defineProperty" ),
2103]
2104
dbeam1ec68ac2016-12-15 05:22:242105def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022106 """Make sure that we don't use deprecated JS in Chrome code."""
2107 results = []
2108 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2109 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2110 input_api.DEFAULT_BLACK_LIST)
2111 file_filter = lambda f: input_api.FilterSourceFile(
2112 f, white_list=file_inclusion_pattern, black_list=black_list)
2113 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2114 for lnum, line in fpath.ChangedContents():
2115 for (deprecated, replacement) in _DEPRECATED_JS:
2116 if deprecated in line:
2117 results.append(output_api.PresubmitError(
2118 "%s:%d: Use of deprecated JS %s, use %s instead" %
2119 (fpath.LocalPath(), lnum, deprecated, replacement)))
2120 return results
2121
dpapadd651231d82017-07-21 02:44:472122def _CheckForRiskyJsArrowFunction(line_number, line):
2123 if ' => ' in line:
2124 return "line %d, is using an => (arrow) function\n %s\n" % (
2125 line_number, line)
2126 return ''
2127
2128def _CheckForRiskyJsConstLet(input_api, line_number, line):
2129 if input_api.re.match('^\s*(const|let)\s', line):
2130 return "line %d, is using const/let keyword\n %s\n" % (
2131 line_number, line)
2132 return ''
dbeam070cfe62014-10-22 06:44:022133
dbeam1ec68ac2016-12-15 05:22:242134def _CheckForRiskyJsFeatures(input_api, output_api):
2135 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002136 # 'ui/webui/resources/cr_components are not allowed on ios'
2137 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572138 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002139 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472140 results = []
dbeam1ec68ac2016-12-15 05:22:242141 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472142 arrow_error_lines = []
2143 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242144 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472145 arrow_error_lines += filter(None, [
2146 _CheckForRiskyJsArrowFunction(lnum, line),
2147 ])
dbeam1ec68ac2016-12-15 05:22:242148
dpapadd651231d82017-07-21 02:44:472149 const_let_error_lines += filter(None, [
2150 _CheckForRiskyJsConstLet(input_api, lnum, line),
2151 ])
dbeam1ec68ac2016-12-15 05:22:242152
dpapadd651231d82017-07-21 02:44:472153 if arrow_error_lines:
2154 arrow_error_lines = map(
2155 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2156 results.append(
2157 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2158"""
2159Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242160%s
2161Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2162https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472163""" % f.LocalPath()
2164 ])))
dbeam1ec68ac2016-12-15 05:22:242165
dpapadd651231d82017-07-21 02:44:472166 if const_let_error_lines:
2167 const_let_error_lines = map(
2168 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2169 results.append(
2170 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2171"""
2172Use of const/let keywords detected in:
2173%s
2174Please ensure your code does not run on iOS9 because const/let is not fully
2175supported.
2176https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2177https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2178""" % f.LocalPath()
2179 ])))
2180
2181 return results
dbeam1ec68ac2016-12-15 05:22:242182
rlanday6802cf632017-05-30 17:48:362183def _CheckForRelativeIncludes(input_api, output_api):
2184 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2185 import sys
2186 original_sys_path = sys.path
2187 try:
2188 sys.path = sys.path + [input_api.os_path.join(
2189 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2190 from cpp_checker import CppChecker
2191 finally:
2192 # Restore sys.path to what it was before.
2193 sys.path = original_sys_path
2194
2195 bad_files = {}
2196 for f in input_api.AffectedFiles(include_deletes=False):
2197 if (f.LocalPath().startswith('third_party') and
2198 not f.LocalPath().startswith('third_party/WebKit') and
2199 not f.LocalPath().startswith('third_party\\WebKit')):
2200 continue
2201
2202 if not CppChecker.IsCppFile(f.LocalPath()):
2203 continue
2204
2205 relative_includes = [line for line_num, line in f.ChangedContents()
2206 if "#include" in line and "../" in line]
2207 if not relative_includes:
2208 continue
2209 bad_files[f.LocalPath()] = relative_includes
2210
2211 if not bad_files:
2212 return []
2213
2214 error_descriptions = []
2215 for file_path, bad_lines in bad_files.iteritems():
2216 error_description = file_path
2217 for line in bad_lines:
2218 error_description += '\n ' + line
2219 error_descriptions.append(error_description)
2220
2221 results = []
2222 results.append(output_api.PresubmitError(
2223 'You added one or more relative #include paths (including "../").\n'
2224 'These shouldn\'t be used because they can be used to include headers\n'
2225 'from code that\'s not correctly specified as a dependency in the\n'
2226 'relevant BUILD.gn file(s).',
2227 error_descriptions))
2228
2229 return results
2230
Takeshi Yoshinoe387aa32017-08-02 13:16:132231
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202232def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2233 if not isinstance(key, ast.Str):
2234 return 'Key at line %d must be a string literal' % key.lineno
2235 if not isinstance(value, ast.Dict):
2236 return 'Value at line %d must be a dict' % value.lineno
2237 if len(value.keys) != 1:
2238 return 'Dict at line %d must have single entry' % value.lineno
2239 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2240 return (
2241 'Entry at line %d must have a string literal \'filepath\' as key' %
2242 value.lineno)
2243 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132244
Takeshi Yoshinoe387aa32017-08-02 13:16:132245
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202246def _CheckWatchlistsEntrySyntax(key, value, ast):
2247 if not isinstance(key, ast.Str):
2248 return 'Key at line %d must be a string literal' % key.lineno
2249 if not isinstance(value, ast.List):
2250 return 'Value at line %d must be a list' % value.lineno
2251 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132252
Takeshi Yoshinoe387aa32017-08-02 13:16:132253
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202254def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2255 mismatch_template = (
2256 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2257 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132258
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202259 i = 0
2260 last_key = ''
2261 while True:
2262 if i >= len(wd_dict.keys):
2263 if i >= len(w_dict.keys):
2264 return None
2265 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2266 elif i >= len(w_dict.keys):
2267 return (
2268 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132269
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202270 wd_key = wd_dict.keys[i]
2271 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132272
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202273 result = _CheckWatchlistDefinitionsEntrySyntax(
2274 wd_key, wd_dict.values[i], ast)
2275 if result is not None:
2276 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132277
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202278 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2279 if result is not None:
2280 return 'Bad entry in WATCHLISTS dict: %s' % result
2281
2282 if wd_key.s != w_key.s:
2283 return mismatch_template % (
2284 '%s at line %d' % (wd_key.s, wd_key.lineno),
2285 '%s at line %d' % (w_key.s, w_key.lineno))
2286
2287 if wd_key.s < last_key:
2288 return (
2289 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2290 (wd_key.lineno, w_key.lineno))
2291 last_key = wd_key.s
2292
2293 i = i + 1
2294
2295
2296def _CheckWATCHLISTSSyntax(expression, ast):
2297 if not isinstance(expression, ast.Expression):
2298 return 'WATCHLISTS file must contain a valid expression'
2299 dictionary = expression.body
2300 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2301 return 'WATCHLISTS file must have single dict with exactly two entries'
2302
2303 first_key = dictionary.keys[0]
2304 first_value = dictionary.values[0]
2305 second_key = dictionary.keys[1]
2306 second_value = dictionary.values[1]
2307
2308 if (not isinstance(first_key, ast.Str) or
2309 first_key.s != 'WATCHLIST_DEFINITIONS' or
2310 not isinstance(first_value, ast.Dict)):
2311 return (
2312 'The first entry of the dict in WATCHLISTS file must be '
2313 'WATCHLIST_DEFINITIONS dict')
2314
2315 if (not isinstance(second_key, ast.Str) or
2316 second_key.s != 'WATCHLISTS' or
2317 not isinstance(second_value, ast.Dict)):
2318 return (
2319 'The second entry of the dict in WATCHLISTS file must be '
2320 'WATCHLISTS dict')
2321
2322 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132323
2324
2325def _CheckWATCHLISTS(input_api, output_api):
2326 for f in input_api.AffectedFiles(include_deletes=False):
2327 if f.LocalPath() == 'WATCHLISTS':
2328 contents = input_api.ReadFile(f, 'r')
2329
2330 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202331 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132332 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202333 # Get an AST tree for it and scan the tree for detailed style checking.
2334 expression = input_api.ast.parse(
2335 contents, filename='WATCHLISTS', mode='eval')
2336 except ValueError as e:
2337 return [output_api.PresubmitError(
2338 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2339 except SyntaxError as e:
2340 return [output_api.PresubmitError(
2341 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2342 except TypeError as e:
2343 return [output_api.PresubmitError(
2344 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132345
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202346 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2347 if result is not None:
2348 return [output_api.PresubmitError(result)]
2349 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132350
2351 return []
2352
2353
dgnaa68d5e2015-06-10 10:08:222354def _AndroidSpecificOnUploadChecks(input_api, output_api):
2355 """Groups checks that target android code."""
2356 results = []
dgnaa68d5e2015-06-10 10:08:222357 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222358 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292359 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062360 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2361 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422362 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222363 return results
2364
2365
[email protected]22c9bd72011-03-27 16:47:392366def _CommonChecks(input_api, output_api):
2367 """Checks common to both upload and commit."""
2368 results = []
2369 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382370 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542371 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582372 results.extend(
2373 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192374 results.extend(
[email protected]760deea2013-12-10 19:33:492375 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542376 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182377 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522378 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222379 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442380 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592381 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062382 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122383 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182384 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222385 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302386 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492387 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032388 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492389 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442390 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272391 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072392 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542393 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442394 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392395 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552396 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042397 results.extend(
2398 input_api.canned_checks.CheckChangeHasNoTabs(
2399 input_api,
2400 output_api,
2401 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402402 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162403 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082404 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242405 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2406 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472407 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042408 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232409 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432410 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402411 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152412 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172413 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502414 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242415 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362416 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132417 results.extend(_CheckWATCHLISTS(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242418
2419 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2420 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2421 input_api, output_api,
2422 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382423 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392424 return results
[email protected]1f7b4172010-01-28 01:17:342425
[email protected]b337cb5b2011-01-23 21:24:052426
[email protected]b8079ae4a2012-12-05 19:56:492427def _CheckPatchFiles(input_api, output_api):
2428 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2429 if f.LocalPath().endswith(('.orig', '.rej'))]
2430 if problems:
2431 return [output_api.PresubmitError(
2432 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032433 else:
2434 return []
[email protected]b8079ae4a2012-12-05 19:56:492435
2436
Kent Tamura5a8755d2017-06-29 23:37:072437def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212438 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2439 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2440 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072441 include_re = input_api.re.compile(
2442 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2443 extension_re = input_api.re.compile(r'\.[a-z]+$')
2444 errors = []
2445 for f in input_api.AffectedFiles():
2446 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2447 continue
2448 found_line_number = None
2449 found_macro = None
2450 for line_num, line in f.ChangedContents():
2451 match = macro_re.search(line)
2452 if match:
2453 found_line_number = line_num
2454 found_macro = match.group(2)
2455 break
2456 if not found_line_number:
2457 continue
2458
2459 found_include = False
2460 for line in f.NewContents():
2461 if include_re.search(line):
2462 found_include = True
2463 break
2464 if found_include:
2465 continue
2466
2467 if not f.LocalPath().endswith('.h'):
2468 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2469 try:
2470 content = input_api.ReadFile(primary_header_path, 'r')
2471 if include_re.search(content):
2472 continue
2473 except IOError:
2474 pass
2475 errors.append('%s:%d %s macro is used without including build/'
2476 'build_config.h.'
2477 % (f.LocalPath(), found_line_number, found_macro))
2478 if errors:
2479 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2480 return []
2481
2482
[email protected]b00342e7f2013-03-26 16:21:542483def _DidYouMeanOSMacro(bad_macro):
2484 try:
2485 return {'A': 'OS_ANDROID',
2486 'B': 'OS_BSD',
2487 'C': 'OS_CHROMEOS',
2488 'F': 'OS_FREEBSD',
2489 'L': 'OS_LINUX',
2490 'M': 'OS_MACOSX',
2491 'N': 'OS_NACL',
2492 'O': 'OS_OPENBSD',
2493 'P': 'OS_POSIX',
2494 'S': 'OS_SOLARIS',
2495 'W': 'OS_WIN'}[bad_macro[3].upper()]
2496 except KeyError:
2497 return ''
2498
2499
2500def _CheckForInvalidOSMacrosInFile(input_api, f):
2501 """Check for sensible looking, totally invalid OS macros."""
2502 preprocessor_statement = input_api.re.compile(r'^\s*#')
2503 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2504 results = []
2505 for lnum, line in f.ChangedContents():
2506 if preprocessor_statement.search(line):
2507 for match in os_macro.finditer(line):
2508 if not match.group(1) in _VALID_OS_MACROS:
2509 good = _DidYouMeanOSMacro(match.group(1))
2510 did_you_mean = ' (did you mean %s?)' % good if good else ''
2511 results.append(' %s:%d %s%s' % (f.LocalPath(),
2512 lnum,
2513 match.group(1),
2514 did_you_mean))
2515 return results
2516
2517
2518def _CheckForInvalidOSMacros(input_api, output_api):
2519 """Check all affected files for invalid OS macros."""
2520 bad_macros = []
2521 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472522 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542523 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2524
2525 if not bad_macros:
2526 return []
2527
2528 return [output_api.PresubmitError(
2529 'Possibly invalid OS macro[s] found. Please fix your code\n'
2530 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2531
lliabraa35bab3932014-10-01 12:16:442532
2533def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2534 """Check all affected files for invalid "if defined" macros."""
2535 ALWAYS_DEFINED_MACROS = (
2536 "TARGET_CPU_PPC",
2537 "TARGET_CPU_PPC64",
2538 "TARGET_CPU_68K",
2539 "TARGET_CPU_X86",
2540 "TARGET_CPU_ARM",
2541 "TARGET_CPU_MIPS",
2542 "TARGET_CPU_SPARC",
2543 "TARGET_CPU_ALPHA",
2544 "TARGET_IPHONE_SIMULATOR",
2545 "TARGET_OS_EMBEDDED",
2546 "TARGET_OS_IPHONE",
2547 "TARGET_OS_MAC",
2548 "TARGET_OS_UNIX",
2549 "TARGET_OS_WIN32",
2550 )
2551 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2552 results = []
2553 for lnum, line in f.ChangedContents():
2554 for match in ifdef_macro.finditer(line):
2555 if match.group(1) in ALWAYS_DEFINED_MACROS:
2556 always_defined = ' %s is always defined. ' % match.group(1)
2557 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2558 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2559 lnum,
2560 always_defined,
2561 did_you_mean))
2562 return results
2563
2564
2565def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2566 """Check all affected files for invalid "if defined" macros."""
2567 bad_macros = []
2568 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212569 if f.LocalPath().startswith('third_party/sqlite/'):
2570 continue
lliabraa35bab3932014-10-01 12:16:442571 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2572 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2573
2574 if not bad_macros:
2575 return []
2576
2577 return [output_api.PresubmitError(
2578 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2579 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2580 bad_macros)]
2581
2582
mlamouria82272622014-09-16 18:45:042583def _CheckForIPCRules(input_api, output_api):
2584 """Check for same IPC rules described in
2585 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2586 """
2587 base_pattern = r'IPC_ENUM_TRAITS\('
2588 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2589 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2590
2591 problems = []
2592 for f in input_api.AffectedSourceFiles(None):
2593 local_path = f.LocalPath()
2594 if not local_path.endswith('.h'):
2595 continue
2596 for line_number, line in f.ChangedContents():
2597 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2598 problems.append(
2599 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2600
2601 if problems:
2602 return [output_api.PresubmitPromptWarning(
2603 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2604 else:
2605 return []
2606
[email protected]b00342e7f2013-03-26 16:21:542607
mostynbb639aca52015-01-07 20:31:232608def _CheckForWindowsLineEndings(input_api, output_api):
2609 """Check source code and known ascii text files for Windows style line
2610 endings.
2611 """
earthdok1b5e0ee2015-03-10 15:19:102612 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232613
2614 file_inclusion_pattern = (
2615 known_text_files,
2616 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2617 )
2618
2619 filter = lambda f: input_api.FilterSourceFile(
2620 f, white_list=file_inclusion_pattern, black_list=None)
2621 files = [f.LocalPath() for f in
2622 input_api.AffectedSourceFiles(filter)]
2623
2624 problems = []
2625
2626 for file in files:
2627 fp = open(file, 'r')
2628 for line in fp:
2629 if line.endswith('\r\n'):
2630 problems.append(file)
2631 break
2632 fp.close()
2633
2634 if problems:
2635 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2636 'these files to contain Windows style line endings?\n' +
2637 '\n'.join(problems))]
2638
2639 return []
2640
2641
pastarmovj89f7ee12016-09-20 14:58:132642def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2643 lint_filters=None, verbose_level=None):
2644 """Checks that all source files use SYSLOG properly."""
2645 syslog_files = []
2646 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562647 for line_number, line in f.ChangedContents():
2648 if 'SYSLOG' in line:
2649 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2650
pastarmovj89f7ee12016-09-20 14:58:132651 if syslog_files:
2652 return [output_api.PresubmitPromptWarning(
2653 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2654 ' calls.\nFiles to check:\n', items=syslog_files)]
2655 return []
2656
2657
[email protected]1f7b4172010-01-28 01:17:342658def CheckChangeOnUpload(input_api, output_api):
2659 results = []
2660 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472661 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282662 results.extend(
jam93a6ee792017-02-08 23:59:222663 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192664 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222665 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132666 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162667 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542668 return results
[email protected]ca8d1982009-02-19 16:33:122669
2670
[email protected]1bfb8322014-04-23 01:02:412671def GetTryServerMasterForBot(bot):
2672 """Returns the Try Server master for the given bot.
2673
[email protected]0bb112362014-07-26 04:38:322674 It tries to guess the master from the bot name, but may still fail
2675 and return None. There is no longer a default master.
2676 """
2677 # Potentially ambiguous bot names are listed explicitly.
2678 master_map = {
tandriie5587792016-07-14 00:34:502679 'chromium_presubmit': 'master.tryserver.chromium.linux',
2680 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412681 }
[email protected]0bb112362014-07-26 04:38:322682 master = master_map.get(bot)
2683 if not master:
wnwen4fbaab82016-05-25 12:54:362684 if 'android' in bot:
tandriie5587792016-07-14 00:34:502685 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362686 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502687 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322688 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502689 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322690 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502691 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322692 return master
[email protected]1bfb8322014-04-23 01:02:412693
2694
[email protected]ca8d1982009-02-19 16:33:122695def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542696 results = []
[email protected]1f7b4172010-01-28 01:17:342697 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542698 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272699 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342700 input_api,
2701 output_api,
[email protected]2fdd1f362013-01-16 03:56:032702 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272703
jam93a6ee792017-02-08 23:59:222704 results.extend(
2705 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542706 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2707 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412708 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2709 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542710 return results