blob: a29e0a0756a4b4d688b602c56ab6e0012fd5c683 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d19842009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d19842009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
primiano0166ccc82015-10-06 12:12:2819 r"^third_party[\\\/]WebKit[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
vapierb2053f542017-03-09 19:46:1026 r"tools[\\\/]md_browser[\\\/].*\.css$",
ehmaldonado78eee2ed2017-03-28 13:16:5427 # Test pages for WebRTC telemetry tests.
28 r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4029)
[email protected]ca8d19842009-02-19 16:33:1230
wnwenbdc444e2016-05-25 13:44:1531
[email protected]06e6d0ff2012-12-11 01:36:4432# Fragment of a regular expression that matches C++ and Objective-C++
33# implementation files.
34_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
35
wnwenbdc444e2016-05-25 13:44:1536
[email protected]06e6d0ff2012-12-11 01:36:4437# Regular expression that matches code only used for test binaries
38# (best effort).
39_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4940 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4441 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
sdefresne1fccb0a2016-12-19 08:10:5342 r'.+_(api|browser|eg|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1243 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4444 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4945 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0546 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4947 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4748 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4949 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0850 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4951 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4452)
[email protected]ca8d19842009-02-19 16:33:1253
wnwenbdc444e2016-05-25 13:44:1554
[email protected]eea609a2011-11-18 13:10:1255_TEST_ONLY_WARNING = (
56 'You might be calling functions intended only for testing from\n'
57 'production code. It is OK to ignore this warning if you know what\n'
58 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5859 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1260
61
[email protected]cf9b78f2012-11-14 11:40:2862_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4063 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2164 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
65 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2866
wnwenbdc444e2016-05-25 13:44:1567
[email protected]127f18ec2012-06-16 05:05:5968_BANNED_OBJC_FUNCTIONS = (
69 (
70 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2071 (
72 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5973 'prohibited. Please use CrTrackingArea instead.',
74 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
75 ),
76 False,
77 ),
78 (
[email protected]eaae1972014-04-16 04:17:2679 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2080 (
81 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5982 'instead.',
83 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
84 ),
85 False,
86 ),
87 (
88 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2089 (
90 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5991 'Please use |convertPoint:(point) fromView:nil| instead.',
92 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
93 ),
94 True,
95 ),
96 (
97 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:2098 (
99 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59100 'Please use |convertPoint:(point) toView:nil| instead.',
101 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
102 ),
103 True,
104 ),
105 (
106 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20107 (
108 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59109 'Please use |convertRect:(point) fromView:nil| instead.',
110 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
111 ),
112 True,
113 ),
114 (
115 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20116 (
117 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59118 'Please use |convertRect:(point) toView:nil| instead.',
119 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
120 ),
121 True,
122 ),
123 (
124 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20125 (
126 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59127 'Please use |convertSize:(point) fromView:nil| instead.',
128 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
129 ),
130 True,
131 ),
132 (
133 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20134 (
135 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59136 'Please use |convertSize:(point) toView:nil| instead.',
137 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
138 ),
139 True,
140 ),
jif65398702016-10-27 10:19:48141 (
142 r"/\s+UTF8String\s*]",
143 (
144 'The use of -[NSString UTF8String] is dangerous as it can return null',
145 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
146 'Please use |SysNSStringToUTF8| instead.',
147 ),
148 True,
149 ),
[email protected]127f18ec2012-06-16 05:05:59150)
151
152
153_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20154 # Make sure that gtest's FRIEND_TEST() macro is not used; the
155 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30156 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20157 (
thomasandersone7caaa9b2017-03-29 19:22:53158 r'\bNULL\b',
159 (
160 'New code should not use NULL. Use nullptr instead.',
161 ),
162 True,
163 (),
164 ),
165 (
[email protected]23e6cbc2012-06-16 18:51:20166 'FRIEND_TEST(',
167 (
[email protected]e3c945502012-06-26 20:01:49168 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20169 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
170 ),
171 False,
[email protected]7345da02012-11-27 14:31:49172 (),
[email protected]23e6cbc2012-06-16 18:51:20173 ),
174 (
thomasanderson4b569052016-09-14 20:15:53175 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
176 (
177 'Chrome clients wishing to select events on X windows should use',
178 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
179 'you are selecting events from the GPU process, or if you are using',
180 'an XDisplay other than gfx::GetXDisplay().',
181 ),
182 True,
183 (
184 r"^ui[\\\/]gl[\\\/].*\.cc$",
185 r"^media[\\\/]gpu[\\\/].*\.cc$",
186 r"^gpu[\\\/].*\.cc$",
187 ),
188 ),
189 (
thomasandersone043e3ce2017-06-08 00:43:20190 r'XInternAtom|xcb_intern_atom',
191 (
thomasanderson11aa41d2017-06-08 22:22:38192 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20193 ),
194 True,
195 (
thomasanderson11aa41d2017-06-08 22:22:38196 r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$",
197 r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20198 r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$",
199 ),
200 ),
201 (
[email protected]23e6cbc2012-06-16 18:51:20202 'ScopedAllowIO',
203 (
satoruxe1396f8a2017-06-01 06:40:39204 'New production code should not use ScopedAllowIO (using it in',
Marijn Kruisselbrink085ef092017-07-12 23:56:55205 'tests is fine). Post a task to a MayBlock task runner instead.',
[email protected]23e6cbc2012-06-16 18:51:20206 ),
[email protected]e3c945502012-06-26 20:01:49207 True,
[email protected]7345da02012-11-27 14:31:49208 (
Marijn Kruisselbrink085ef092017-07-12 23:56:55209 r"^.*(browser|unit)(|_)test[a-z_]*\.cc$",
hajimehoshi2acea432017-03-08 08:55:37210 r"^base[\\\/]memory[\\\/]shared_memory_posix\.cc$",
rayb0088ee52017-04-26 22:35:08211 r"^base[\\\/]process[\\\/]internal_aix\.cc$",
nyad2c548b2015-12-09 03:22:32212 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10213 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
tfarina0923ac52015-01-07 03:21:22214 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
rdevlin.cronin62018a12017-06-22 17:34:06215 r"^chrome[\\\/]browser[\\\/]extensions[\\\/]" +
216 r"chrome_test_extension_loader.cc$",
sky0e07a142016-03-25 21:27:31217 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
philipj3f9d5bde2014-08-28 14:09:09218 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49219 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
220 r"test_info_extractor\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41221 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
222 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25223 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
miu8e0e80c2017-05-31 03:35:57224 r"^media[\\\/]cast[\\\/]test[\\\/]utility[\\\/]" +
225 r"standalone_cast_environment\.cc$",
jamesra03ae492014-10-03 04:26:48226 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
227 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01228 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25229 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
230 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
231 r"embedded_test_server\.cc$",
232 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
233 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54234 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
sergeyu2c41f9842016-12-10 01:45:16235 r"^remoting[\\\/]protocol[\\\/]webrtc_transport\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53236 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
237 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45238 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
239 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
240 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
241 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
242 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49243 ),
[email protected]23e6cbc2012-06-16 18:51:20244 ),
[email protected]52657f62013-05-20 05:30:31245 (
tomhudsone2c14d552016-05-26 17:07:46246 'setMatrixClip',
247 (
248 'Overriding setMatrixClip() is prohibited; ',
249 'the base function is deprecated. ',
250 ),
251 True,
252 (),
253 ),
254 (
[email protected]52657f62013-05-20 05:30:31255 'SkRefPtr',
256 (
257 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22258 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31259 ),
260 True,
261 (),
262 ),
263 (
264 'SkAutoRef',
265 (
266 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22267 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31268 ),
269 True,
270 (),
271 ),
272 (
273 'SkAutoTUnref',
274 (
275 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22276 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31277 ),
278 True,
279 (),
280 ),
281 (
282 'SkAutoUnref',
283 (
284 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
285 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22286 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31287 ),
288 True,
289 (),
290 ),
[email protected]d89eec82013-12-03 14:10:59291 (
292 r'/HANDLE_EINTR\(.*close',
293 (
294 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
295 'descriptor will be closed, and it is incorrect to retry the close.',
296 'Either call close directly and ignore its return value, or wrap close',
297 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
298 ),
299 True,
300 (),
301 ),
302 (
303 r'/IGNORE_EINTR\((?!.*close)',
304 (
305 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
306 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
307 ),
308 True,
309 (
310 # Files that #define IGNORE_EINTR.
311 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
312 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
313 ),
314 ),
[email protected]ec5b3f02014-04-04 18:43:43315 (
316 r'/v8::Extension\(',
317 (
318 'Do not introduce new v8::Extensions into the code base, use',
319 'gin::Wrappable instead. See http://crbug.com/334679',
320 ),
321 True,
[email protected]f55c90ee62014-04-12 00:50:03322 (
joaodasilva718f87672014-08-30 09:25:49323 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03324 ),
[email protected]ec5b3f02014-04-04 18:43:43325 ),
skyostilf9469f72015-04-20 10:38:52326 (
jame2d1a952016-04-02 00:27:10327 '#pragma comment(lib,',
328 (
329 'Specify libraries to link with in build files and not in the source.',
330 ),
331 True,
332 (),
333 ),
fdorayc4ac18d2017-05-01 21:39:59334 (
Francois Dorayd7c671722017-08-01 17:31:39335 r'/(WebThread|BrowserThread)::GetBlockingPool',
fdorayc4ac18d2017-05-01 21:39:59336 (
337 'Use base/task_scheduler/post_task.h instead of the blocking pool. See',
338 'mapping between both APIs in content/public/browser/browser_thread.h.',
339 'For questions, contact base/task_scheduler/OWNERS.',
340 ),
341 True,
342 (),
343 ),
gabd52c912a2017-05-11 04:15:59344 (
Kevin Marshall342ddd62017-08-24 17:22:36345 r'/(WebThread|BrowserThread)::(FILE|FILE_USER_BLOCKING|DB|CACHE)',
Gabriel Charette664e4482017-06-13 19:55:29346 (
347 'The non-UI/IO BrowserThreads are deprecated, please migrate this',
348 'code to TaskScheduler. See https://goo.gl/mDSxKl for details.',
349 'For questions, contact base/task_scheduler/OWNERS.',
350 ),
351 True,
352 (),
353 ),
354 (
gabd52c912a2017-05-11 04:15:59355 'base::SequenceChecker',
356 (
357 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
358 ),
359 False,
360 (),
361 ),
362 (
363 'base::ThreadChecker',
364 (
365 'Consider using THREAD_CHECKER macros instead of the class directly.',
366 ),
367 False,
368 (),
369 ),
dbeamb6f4fde2017-06-15 04:03:06370 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06371 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
372 (
373 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
374 'deprecated (http://crbug.com/634507). Please avoid converting away',
375 'from the Time types in Chromium code, especially if any math is',
376 'being done on time values. For interfacing with platform/library',
377 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
378 'type converter methods instead. For faking TimeXXX values (for unit',
379 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
380 'other use cases, please contact base/time/OWNERS.',
381 ),
382 False,
383 (),
384 ),
385 (
dbeamb6f4fde2017-06-15 04:03:06386 'CallJavascriptFunctionUnsafe',
387 (
388 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
389 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
390 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
391 ),
392 False,
393 (
394 r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$',
395 r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$',
396 r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$',
397 ),
398 ),
dskiba1474c2bfd62017-07-20 02:19:24399 (
400 'leveldb::DB::Open',
401 (
402 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
403 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
404 "Chrome's tracing, making their memory usage visible.",
405 ),
406 True,
407 (
408 r'^third_party/leveldatabase/.*\.(cc|h)$',
409 ),
Gabriel Charette0592c3a2017-07-26 12:02:04410 ),
411 (
Gabriel Charetted9839bc2017-07-29 14:17:47412 'MessageLoop::QuitWhenIdleClosure',
Gabriel Charette0592c3a2017-07-26 12:02:04413 (
Robert Liao64b7ab22017-08-04 23:03:43414 'MessageLoop::QuitWhenIdleClosure is deprecated. Please migrate to',
415 'Runloop.',
Gabriel Charette0592c3a2017-07-26 12:02:04416 ),
417 True,
418 (),
Gabriel Charetted9839bc2017-07-29 14:17:47419 ),
420 (
421 'RunLoop::QuitCurrent',
422 (
Robert Liao64b7ab22017-08-04 23:03:43423 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
424 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47425 ),
426 True,
427 (),
Gabriel Charettea44975052017-08-21 23:14:04428 ),
429 (
430 'base::ScopedMockTimeMessageLoopTaskRunner',
431 (
432 'ScopedMockTimeMessageLoopTaskRunner is deprecated.',
433 ),
434 True,
435 (),
dskiba1474c2bfd62017-07-20 02:19:24436 )
[email protected]127f18ec2012-06-16 05:05:59437)
438
wnwenbdc444e2016-05-25 13:44:15439
mlamouria82272622014-09-16 18:45:04440_IPC_ENUM_TRAITS_DEPRECATED = (
441 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
442 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
443
[email protected]127f18ec2012-06-16 05:05:59444
Sean Kau46e29bc2017-08-28 16:31:16445# These paths contain test data and other known invalid JSON files.
446_KNOWN_INVALID_JSON_FILE_PATTERNS = [
447 r'test[\\\/]data[\\\/]',
448 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
449 r'^third_party[\\\/]protobuf[\\\/]',
450]
451
452
[email protected]b00342e7f2013-03-26 16:21:54453_VALID_OS_MACROS = (
454 # Please keep sorted.
rayb0088ee52017-04-26 22:35:08455 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:54456 'OS_ANDROID',
457 'OS_BSD',
458 'OS_CAT', # For testing.
459 'OS_CHROMEOS',
460 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:37461 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:54462 'OS_IOS',
463 'OS_LINUX',
464 'OS_MACOSX',
465 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21466 'OS_NACL_NONSFI',
467 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12468 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54469 'OS_OPENBSD',
470 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37471 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54472 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54473 'OS_WIN',
474)
475
476
agrievef32bcc72016-04-04 14:57:40477_ANDROID_SPECIFIC_PYDEPS_FILES = [
478 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04479 'build/android/test_wrapper/logdog_wrapper.pydeps',
jbudorick276cc562017-04-29 01:34:58480 'build/secondary/third_party/android_platform/'
481 'development/scripts/stack.pydeps',
agrieve732db3a2016-04-26 19:18:19482 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40483]
484
wnwenbdc444e2016-05-25 13:44:15485
agrievef32bcc72016-04-04 14:57:40486_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40487]
488
wnwenbdc444e2016-05-25 13:44:15489
agrievef32bcc72016-04-04 14:57:40490_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
491
492
[email protected]55459852011-08-10 15:17:19493def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
494 """Attempts to prevent use of functions intended only for testing in
495 non-testing code. For now this is just a best-effort implementation
496 that ignores header files and may have some false positives. A
497 better implementation would probably need a proper C++ parser.
498 """
499 # We only scan .cc files and the like, as the declaration of
500 # for-testing functions in header files are hard to distinguish from
501 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44502 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19503
jochenc0d4808c2015-07-27 09:25:42504 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19505 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09506 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19507 exclusion_pattern = input_api.re.compile(
508 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
509 base_function_pattern, base_function_pattern))
510
511 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44512 black_list = (_EXCLUDED_PATHS +
513 _TEST_CODE_EXCLUDED_PATHS +
514 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19515 return input_api.FilterSourceFile(
516 affected_file,
517 white_list=(file_inclusion_pattern, ),
518 black_list=black_list)
519
520 problems = []
521 for f in input_api.AffectedSourceFiles(FilterFile):
522 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24523 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03524 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46525 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03526 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19527 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03528 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19529
530 if problems:
[email protected]f7051d52013-04-02 18:31:42531 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03532 else:
533 return []
[email protected]55459852011-08-10 15:17:19534
535
[email protected]10689ca2011-09-02 02:31:54536def _CheckNoIOStreamInHeaders(input_api, output_api):
537 """Checks to make sure no .h files include <iostream>."""
538 files = []
539 pattern = input_api.re.compile(r'^#include\s*<iostream>',
540 input_api.re.MULTILINE)
541 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
542 if not f.LocalPath().endswith('.h'):
543 continue
544 contents = input_api.ReadFile(f)
545 if pattern.search(contents):
546 files.append(f)
547
548 if len(files):
yolandyandaabc6d2016-04-18 18:29:39549 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06550 'Do not #include <iostream> in header files, since it inserts static '
551 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54552 '#include <ostream>. See http://crbug.com/94794',
553 files) ]
554 return []
555
556
[email protected]72df4e782012-06-21 16:28:18557def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52558 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18559 problems = []
560 for f in input_api.AffectedFiles():
561 if (not f.LocalPath().endswith(('.cc', '.mm'))):
562 continue
563
564 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04565 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18566 problems.append(' %s:%d' % (f.LocalPath(), line_num))
567
568 if not problems:
569 return []
570 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
571 '\n'.join(problems))]
572
573
danakj61c1aa22015-10-26 19:55:52574def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57575 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52576 errors = []
577 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
578 input_api.re.MULTILINE)
579 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
580 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
581 continue
582 for lnum, line in f.ChangedContents():
583 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17584 errors.append(output_api.PresubmitError(
585 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57586 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17587 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52588 return errors
589
590
mcasasb7440c282015-02-04 14:52:19591def _FindHistogramNameInLine(histogram_name, line):
592 """Tries to find a histogram name or prefix in a line."""
593 if not "affected-histogram" in line:
594 return histogram_name in line
595 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
596 # the histogram_name.
597 if not '"' in line:
598 return False
599 histogram_prefix = line.split('\"')[1]
600 return histogram_prefix in histogram_name
601
602
603def _CheckUmaHistogramChanges(input_api, output_api):
604 """Check that UMA histogram names in touched lines can still be found in other
605 lines of the patch or in histograms.xml. Note that this check would not catch
606 the reverse: changes in histograms.xml not matched in the code itself."""
607 touched_histograms = []
608 histograms_xml_modifications = []
609 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
610 for f in input_api.AffectedFiles():
611 # If histograms.xml itself is modified, keep the modified lines for later.
612 if f.LocalPath().endswith(('histograms.xml')):
613 histograms_xml_modifications = f.ChangedContents()
614 continue
615 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
616 continue
617 for line_num, line in f.ChangedContents():
618 found = pattern.search(line)
619 if found:
620 touched_histograms.append([found.group(1), f, line_num])
621
622 # Search for the touched histogram names in the local modifications to
623 # histograms.xml, and, if not found, on the base histograms.xml file.
624 unmatched_histograms = []
625 for histogram_info in touched_histograms:
626 histogram_name_found = False
627 for line_num, line in histograms_xml_modifications:
628 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
629 if histogram_name_found:
630 break
631 if not histogram_name_found:
632 unmatched_histograms.append(histogram_info)
633
eromanb90c82e7e32015-04-01 15:13:49634 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19635 problems = []
636 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49637 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19638 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45639 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19640 histogram_name_found = False
641 for line in histograms_xml:
642 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
643 if histogram_name_found:
644 break
645 if not histogram_name_found:
646 problems.append(' [%s:%d] %s' %
647 (f.LocalPath(), line_num, histogram_name))
648
649 if not problems:
650 return []
651 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
652 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49653 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19654
wnwenbdc444e2016-05-25 13:44:15655
yolandyandaabc6d2016-04-18 18:29:39656def _CheckFlakyTestUsage(input_api, output_api):
657 """Check that FlakyTest annotation is our own instead of the android one"""
658 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
659 files = []
660 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
661 if f.LocalPath().endswith('Test.java'):
662 if pattern.search(input_api.ReadFile(f)):
663 files.append(f)
664 if len(files):
665 return [output_api.PresubmitError(
666 'Use org.chromium.base.test.util.FlakyTest instead of '
667 'android.test.FlakyTest',
668 files)]
669 return []
mcasasb7440c282015-02-04 14:52:19670
wnwenbdc444e2016-05-25 13:44:15671
[email protected]8ea5d4b2011-09-13 21:49:22672def _CheckNoNewWStrings(input_api, output_api):
673 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27674 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22675 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20676 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57677 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34678 '/win/' in f.LocalPath() or
679 'chrome_elf' in f.LocalPath() or
680 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20681 continue
[email protected]8ea5d4b2011-09-13 21:49:22682
[email protected]a11dbe9b2012-08-07 01:32:58683 allowWString = False
[email protected]b5c24292011-11-28 14:38:20684 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58685 if 'presubmit: allow wstring' in line:
686 allowWString = True
687 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27688 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58689 allowWString = False
690 else:
691 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22692
[email protected]55463aa62011-10-12 00:48:27693 if not problems:
694 return []
695 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58696 ' If you are calling a cross-platform API that accepts a wstring, '
697 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27698 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22699
700
[email protected]2a8ac9c2011-10-19 17:20:44701def _CheckNoDEPSGIT(input_api, output_api):
702 """Make sure .DEPS.git is never modified manually."""
703 if any(f.LocalPath().endswith('.DEPS.git') for f in
704 input_api.AffectedFiles()):
705 return [output_api.PresubmitError(
706 'Never commit changes to .DEPS.git. This file is maintained by an\n'
707 'automated system based on what\'s in DEPS and your changes will be\n'
708 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34709 '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:44710 'for more information')]
711 return []
712
713
tandriief664692014-09-23 14:51:47714def _CheckValidHostsInDEPS(input_api, output_api):
715 """Checks that DEPS file deps are from allowed_hosts."""
716 # Run only if DEPS file has been modified to annoy fewer bystanders.
717 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
718 return []
719 # Outsource work to gclient verify
720 try:
721 input_api.subprocess.check_output(['gclient', 'verify'])
722 return []
723 except input_api.subprocess.CalledProcessError, error:
724 return [output_api.PresubmitError(
725 'DEPS file must have only git dependencies.',
726 long_text=error.output)]
727
728
[email protected]127f18ec2012-06-16 05:05:59729def _CheckNoBannedFunctions(input_api, output_api):
730 """Make sure that banned functions are not used."""
731 warnings = []
732 errors = []
733
wnwenbdc444e2016-05-25 13:44:15734 def IsBlacklisted(affected_file, blacklist):
735 local_path = affected_file.LocalPath()
736 for item in blacklist:
737 if input_api.re.match(item, local_path):
738 return True
739 return False
740
741 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
742 matched = False
743 if func_name[0:1] == '/':
744 regex = func_name[1:]
745 if input_api.re.search(regex, line):
746 matched = True
747 elif func_name in line:
dchenge07de812016-06-20 19:27:17748 matched = True
wnwenbdc444e2016-05-25 13:44:15749 if matched:
dchenge07de812016-06-20 19:27:17750 problems = warnings
wnwenbdc444e2016-05-25 13:44:15751 if error:
dchenge07de812016-06-20 19:27:17752 problems = errors
wnwenbdc444e2016-05-25 13:44:15753 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
754 for message_line in message:
755 problems.append(' %s' % message_line)
756
[email protected]127f18ec2012-06-16 05:05:59757 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
758 for f in input_api.AffectedFiles(file_filter=file_filter):
759 for line_num, line in f.ChangedContents():
760 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15761 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59762
763 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
764 for f in input_api.AffectedFiles(file_filter=file_filter):
765 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49766 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49767 if IsBlacklisted(f, excluded_paths):
768 continue
wnwenbdc444e2016-05-25 13:44:15769 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59770
771 result = []
772 if (warnings):
773 result.append(output_api.PresubmitPromptWarning(
774 'Banned functions were used.\n' + '\n'.join(warnings)))
775 if (errors):
776 result.append(output_api.PresubmitError(
777 'Banned functions were used.\n' + '\n'.join(errors)))
778 return result
779
780
[email protected]6c063c62012-07-11 19:11:06781def _CheckNoPragmaOnce(input_api, output_api):
782 """Make sure that banned functions are not used."""
783 files = []
784 pattern = input_api.re.compile(r'^#pragma\s+once',
785 input_api.re.MULTILINE)
786 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
787 if not f.LocalPath().endswith('.h'):
788 continue
789 contents = input_api.ReadFile(f)
790 if pattern.search(contents):
791 files.append(f)
792
793 if files:
794 return [output_api.PresubmitError(
795 'Do not use #pragma once in header files.\n'
796 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
797 files)]
798 return []
799
[email protected]127f18ec2012-06-16 05:05:59800
[email protected]e7479052012-09-19 00:26:12801def _CheckNoTrinaryTrueFalse(input_api, output_api):
802 """Checks to make sure we don't introduce use of foo ? true : false."""
803 problems = []
804 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
805 for f in input_api.AffectedFiles():
806 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
807 continue
808
809 for line_num, line in f.ChangedContents():
810 if pattern.match(line):
811 problems.append(' %s:%d' % (f.LocalPath(), line_num))
812
813 if not problems:
814 return []
815 return [output_api.PresubmitPromptWarning(
816 'Please consider avoiding the "? true : false" pattern if possible.\n' +
817 '\n'.join(problems))]
818
819
[email protected]55f9f382012-07-31 11:02:18820def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28821 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18822 change. Breaking - rules is an error, breaking ! rules is a
823 warning.
824 """
mohan.reddyf21db962014-10-16 12:26:47825 import sys
[email protected]55f9f382012-07-31 11:02:18826 # We need to wait until we have an input_api object and use this
827 # roundabout construct to import checkdeps because this file is
828 # eval-ed and thus doesn't have __file__.
829 original_sys_path = sys.path
830 try:
831 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47832 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18833 import checkdeps
834 from cpp_checker import CppChecker
rhalavati08acd232017-04-03 07:23:28835 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18836 from rules import Rule
837 finally:
838 # Restore sys.path to what it was before.
839 sys.path = original_sys_path
840
841 added_includes = []
rhalavati08acd232017-04-03 07:23:28842 added_imports = []
[email protected]55f9f382012-07-31 11:02:18843 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28844 if CppChecker.IsCppFile(f.LocalPath()):
845 changed_lines = [line for line_num, line in f.ChangedContents()]
846 added_includes.append([f.LocalPath(), changed_lines])
847 elif ProtoChecker.IsProtoFile(f.LocalPath()):
848 changed_lines = [line for line_num, line in f.ChangedContents()]
849 added_imports.append([f.LocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18850
[email protected]26385172013-05-09 23:11:35851 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18852
853 error_descriptions = []
854 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28855 error_subjects = set()
856 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18857 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
858 added_includes):
859 description_with_path = '%s\n %s' % (path, rule_description)
860 if rule_type == Rule.DISALLOW:
861 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28862 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18863 else:
864 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28865 warning_subjects.add("#includes")
866
867 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
868 added_imports):
869 description_with_path = '%s\n %s' % (path, rule_description)
870 if rule_type == Rule.DISALLOW:
871 error_descriptions.append(description_with_path)
872 error_subjects.add("imports")
873 else:
874 warning_descriptions.append(description_with_path)
875 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18876
877 results = []
878 if error_descriptions:
879 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28880 'You added one or more %s that violate checkdeps rules.'
881 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18882 error_descriptions))
883 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42884 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28885 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18886 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28887 '%s? See relevant DEPS file(s) for details and contacts.' %
888 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18889 warning_descriptions))
890 return results
891
892
[email protected]fbcafe5a2012-08-08 15:31:22893def _CheckFilePermissions(input_api, output_api):
894 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15895 if input_api.platform == 'win32':
896 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29897 checkperms_tool = input_api.os_path.join(
898 input_api.PresubmitLocalPath(),
899 'tools', 'checkperms', 'checkperms.py')
900 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47901 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22902 for f in input_api.AffectedFiles():
903 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11904 try:
905 input_api.subprocess.check_output(args)
906 return []
907 except input_api.subprocess.CalledProcessError as error:
908 return [output_api.PresubmitError(
909 'checkperms.py failed:',
910 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22911
912
robertocn832f5992017-01-04 19:01:30913def _CheckTeamTags(input_api, output_api):
914 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
915 checkteamtags_tool = input_api.os_path.join(
916 input_api.PresubmitLocalPath(),
917 'tools', 'checkteamtags', 'checkteamtags.py')
918 args = [input_api.python_executable, checkteamtags_tool,
919 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22920 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30921 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
922 'OWNERS']
923 try:
924 if files:
925 input_api.subprocess.check_output(args + files)
926 return []
927 except input_api.subprocess.CalledProcessError as error:
928 return [output_api.PresubmitError(
929 'checkteamtags.py failed:',
930 long_text=error.output)]
931
932
[email protected]c8278b32012-10-30 20:35:49933def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
934 """Makes sure we don't include ui/aura/window_property.h
935 in header files.
936 """
937 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
938 errors = []
939 for f in input_api.AffectedFiles():
940 if not f.LocalPath().endswith('.h'):
941 continue
942 for line_num, line in f.ChangedContents():
943 if pattern.match(line):
944 errors.append(' %s:%d' % (f.LocalPath(), line_num))
945
946 results = []
947 if errors:
948 results.append(output_api.PresubmitError(
949 'Header files should not include ui/aura/window_property.h', errors))
950 return results
951
952
[email protected]70ca77752012-11-20 03:45:03953def _CheckForVersionControlConflictsInFile(input_api, f):
954 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
955 errors = []
956 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23957 if f.LocalPath().endswith('.md'):
958 # First-level headers in markdown look a lot like version control
959 # conflict markers. http://daringfireball.net/projects/markdown/basics
960 continue
[email protected]70ca77752012-11-20 03:45:03961 if pattern.match(line):
962 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
963 return errors
964
965
966def _CheckForVersionControlConflicts(input_api, output_api):
967 """Usually this is not intentional and will cause a compile failure."""
968 errors = []
969 for f in input_api.AffectedFiles():
970 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
971
972 results = []
973 if errors:
974 results.append(output_api.PresubmitError(
975 'Version control conflict markers found, please resolve.', errors))
976 return results
977
estadee17314a02017-01-12 16:22:16978def _CheckGoogleSupportAnswerUrl(input_api, output_api):
979 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
980 errors = []
981 for f in input_api.AffectedFiles():
982 for line_num, line in f.ChangedContents():
983 if pattern.search(line):
984 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
985
986 results = []
987 if errors:
988 results.append(output_api.PresubmitPromptWarning(
989 'Found Google support URL addressed by answer number. Please replace with '
990 'a p= identifier instead. See crbug.com/679462\n', errors))
991 return results
992
[email protected]70ca77752012-11-20 03:45:03993
[email protected]06e6d0ff2012-12-11 01:36:44994def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
995 def FilterFile(affected_file):
996 """Filter function for use with input_api.AffectedSourceFiles,
997 below. This filters out everything except non-test files from
998 top-level directories that generally speaking should not hard-code
999 service URLs (e.g. src/android_webview/, src/content/ and others).
1000 """
1001 return input_api.FilterSourceFile(
1002 affected_file,
[email protected]78bb39d62012-12-11 15:11:561003 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441004 black_list=(_EXCLUDED_PATHS +
1005 _TEST_CODE_EXCLUDED_PATHS +
1006 input_api.DEFAULT_BLACK_LIST))
1007
reillyi38965732015-11-16 18:27:331008 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1009 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461010 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1011 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441012 problems = [] # items are (filename, line_number, line)
1013 for f in input_api.AffectedSourceFiles(FilterFile):
1014 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461015 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441016 problems.append((f.LocalPath(), line_num, line))
1017
1018 if problems:
[email protected]f7051d52013-04-02 18:31:421019 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441020 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581021 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441022 [' %s:%d: %s' % (
1023 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031024 else:
1025 return []
[email protected]06e6d0ff2012-12-11 01:36:441026
1027
[email protected]d2530012013-01-25 16:39:271028def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1029 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311030 The native_client_sdk directory is excluded because it has auto-generated PNG
1031 files for documentation.
[email protected]d2530012013-01-25 16:39:271032 """
[email protected]d2530012013-01-25 16:39:271033 errors = []
binji0dcdf342014-12-12 18:32:311034 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1035 black_list = (r'^native_client_sdk[\\\/]',)
1036 file_filter = lambda f: input_api.FilterSourceFile(
1037 f, white_list=white_list, black_list=black_list)
1038 for f in input_api.AffectedFiles(include_deletes=False,
1039 file_filter=file_filter):
1040 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271041
1042 results = []
1043 if errors:
1044 results.append(output_api.PresubmitError(
1045 'The name of PNG files should not have abbreviations. \n'
1046 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1047 'Contact [email protected] if you have questions.', errors))
1048 return results
1049
1050
Daniel Cheng4dcdb6b2017-04-13 08:30:171051def _ExtractAddRulesFromParsedDeps(parsed_deps):
1052 """Extract the rules that add dependencies from a parsed DEPS file.
1053
1054 Args:
1055 parsed_deps: the locals dictionary from evaluating the DEPS file."""
1056 add_rules = set()
1057 add_rules.update([
1058 rule[1:] for rule in parsed_deps.get('include_rules', [])
1059 if rule.startswith('+') or rule.startswith('!')
1060 ])
1061 for specific_file, rules in parsed_deps.get('specific_include_rules',
1062 {}).iteritems():
1063 add_rules.update([
1064 rule[1:] for rule in rules
1065 if rule.startswith('+') or rule.startswith('!')
1066 ])
1067 return add_rules
1068
1069
1070def _ParseDeps(contents):
1071 """Simple helper for parsing DEPS files."""
1072 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:171073 class _VarImpl:
1074
1075 def __init__(self, local_scope):
1076 self._local_scope = local_scope
1077
1078 def Lookup(self, var_name):
1079 """Implements the Var syntax."""
1080 try:
1081 return self._local_scope['vars'][var_name]
1082 except KeyError:
1083 raise Exception('Var is not defined: %s' % var_name)
1084
1085 local_scope = {}
1086 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:171087 'Var': _VarImpl(local_scope).Lookup,
1088 }
1089 exec contents in global_scope, local_scope
1090 return local_scope
1091
1092
1093def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:081094 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411095 a set of DEPS entries that we should look up.
1096
1097 For a directory (rather than a specific filename) we fake a path to
1098 a specific filename by adding /DEPS. This is chosen as a file that
1099 will seldom or never be subject to per-file include_rules.
1100 """
[email protected]2b438d62013-11-14 17:54:141101 # We ignore deps entries on auto-generated directories.
1102 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081103
Daniel Cheng4dcdb6b2017-04-13 08:30:171104 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
1105 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
1106
1107 added_deps = new_deps.difference(old_deps)
1108
[email protected]2b438d62013-11-14 17:54:141109 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:171110 for added_dep in added_deps:
1111 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
1112 continue
1113 # Assume that a rule that ends in .h is a rule for a specific file.
1114 if added_dep.endswith('.h'):
1115 results.add(added_dep)
1116 else:
1117 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:081118 return results
1119
1120
[email protected]e871964c2013-05-13 14:14:551121def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1122 """When a dependency prefixed with + is added to a DEPS file, we
1123 want to make sure that the change is reviewed by an OWNER of the
1124 target file or directory, to avoid layering violations from being
1125 introduced. This check verifies that this happens.
1126 """
Daniel Cheng4dcdb6b2017-04-13 08:30:171127 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:241128
1129 file_filter = lambda f: not input_api.re.match(
1130 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1131 for f in input_api.AffectedFiles(include_deletes=False,
1132 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551133 filename = input_api.os_path.basename(f.LocalPath())
1134 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:171135 virtual_depended_on_files.update(_CalculateAddedDeps(
1136 input_api.os_path,
1137 '\n'.join(f.OldContents()),
1138 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:551139
[email protected]e871964c2013-05-13 14:14:551140 if not virtual_depended_on_files:
1141 return []
1142
1143 if input_api.is_committing:
1144 if input_api.tbr:
1145 return [output_api.PresubmitNotifyResult(
1146 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271147 if input_api.dry_run:
1148 return [output_api.PresubmitNotifyResult(
1149 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551150 if not input_api.change.issue:
1151 return [output_api.PresubmitError(
1152 "DEPS approval by OWNERS check failed: this change has "
1153 "no Rietveld issue number, so we can't check it for approvals.")]
1154 output = output_api.PresubmitError
1155 else:
1156 output = output_api.PresubmitNotifyResult
1157
1158 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501159 owner_email, reviewers = (
1160 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1161 input_api,
1162 owners_db.email_regexp,
1163 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551164
1165 owner_email = owner_email or input_api.change.author_email
1166
[email protected]de4f7d22013-05-23 14:27:461167 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511168 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461169 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551170 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1171 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411172
1173 # We strip the /DEPS part that was added by
1174 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1175 # directory.
1176 def StripDeps(path):
1177 start_deps = path.rfind('/DEPS')
1178 if start_deps != -1:
1179 return path[:start_deps]
1180 else:
1181 return path
1182 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551183 for path in missing_files]
1184
1185 if unapproved_dependencies:
1186 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151187 output('You need LGTM from owners of depends-on paths in DEPS that were '
1188 'modified in this CL:\n %s' %
1189 '\n '.join(sorted(unapproved_dependencies)))]
1190 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1191 output_list.append(output(
1192 'Suggested missing target path OWNERS:\n %s' %
1193 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551194 return output_list
1195
1196 return []
1197
1198
[email protected]85218562013-11-22 07:41:401199def _CheckSpamLogging(input_api, output_api):
1200 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1201 black_list = (_EXCLUDED_PATHS +
1202 _TEST_CODE_EXCLUDED_PATHS +
1203 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501204 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191205 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481206 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461207 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121208 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1209 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581210 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
huangsa13b5a02017-07-14 15:17:591211 r"^chrome[\\\/]installer[\\\/]zucchini[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161212 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031213 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151214 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1215 r"^chromecast[\\\/]",
1216 r"^cloud_print[\\\/]",
manzagop85e629e2017-05-09 22:11:481217 r"^components[\\\/]browser_watcher[\\\/]"
1218 r"dump_stability_report_main_win.cc$",
jochen34415e52015-07-10 08:34:311219 r"^components[\\\/]html_viewer[\\\/]"
1220 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461221 # TODO(peter): Remove this exception. https://crbug.com/534537
1222 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1223 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251224 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1225 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241226 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111227 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151228 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111229 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521230 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501231 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361232 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311233 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131234 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001235 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441236 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451237 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021238 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351239 r"dump_file_system.cc$",
1240 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401241 source_file_filter = lambda x: input_api.FilterSourceFile(
1242 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1243
thomasanderson625d3932017-03-29 07:16:581244 log_info = set([])
1245 printf = set([])
[email protected]85218562013-11-22 07:41:401246
1247 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581248 for _, line in f.ChangedContents():
1249 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1250 log_info.add(f.LocalPath())
1251 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1252 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371253
thomasanderson625d3932017-03-29 07:16:581254 if input_api.re.search(r"\bprintf\(", line):
1255 printf.add(f.LocalPath())
1256 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1257 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401258
1259 if log_info:
1260 return [output_api.PresubmitError(
1261 'These files spam the console log with LOG(INFO):',
1262 items=log_info)]
1263 if printf:
1264 return [output_api.PresubmitError(
1265 'These files spam the console log with printf/fprintf:',
1266 items=printf)]
1267 return []
1268
1269
[email protected]49aa76a2013-12-04 06:59:161270def _CheckForAnonymousVariables(input_api, output_api):
1271 """These types are all expected to hold locks while in scope and
1272 so should never be anonymous (which causes them to be immediately
1273 destroyed)."""
1274 they_who_must_be_named = [
1275 'base::AutoLock',
1276 'base::AutoReset',
1277 'base::AutoUnlock',
1278 'SkAutoAlphaRestore',
1279 'SkAutoBitmapShaderInstall',
1280 'SkAutoBlitterChoose',
1281 'SkAutoBounderCommit',
1282 'SkAutoCallProc',
1283 'SkAutoCanvasRestore',
1284 'SkAutoCommentBlock',
1285 'SkAutoDescriptor',
1286 'SkAutoDisableDirectionCheck',
1287 'SkAutoDisableOvalCheck',
1288 'SkAutoFree',
1289 'SkAutoGlyphCache',
1290 'SkAutoHDC',
1291 'SkAutoLockColors',
1292 'SkAutoLockPixels',
1293 'SkAutoMalloc',
1294 'SkAutoMaskFreeImage',
1295 'SkAutoMutexAcquire',
1296 'SkAutoPathBoundsUpdate',
1297 'SkAutoPDFRelease',
1298 'SkAutoRasterClipValidate',
1299 'SkAutoRef',
1300 'SkAutoTime',
1301 'SkAutoTrace',
1302 'SkAutoUnref',
1303 ]
1304 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1305 # bad: base::AutoLock(lock.get());
1306 # not bad: base::AutoLock lock(lock.get());
1307 bad_pattern = input_api.re.compile(anonymous)
1308 # good: new base::AutoLock(lock.get())
1309 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1310 errors = []
1311
1312 for f in input_api.AffectedFiles():
1313 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1314 continue
1315 for linenum, line in f.ChangedContents():
1316 if bad_pattern.search(line) and not good_pattern.search(line):
1317 errors.append('%s:%d' % (f.LocalPath(), linenum))
1318
1319 if errors:
1320 return [output_api.PresubmitError(
1321 'These lines create anonymous variables that need to be named:',
1322 items=errors)]
1323 return []
1324
1325
[email protected]999261d2014-03-03 20:08:081326def _CheckUserActionUpdate(input_api, output_api):
1327 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521328 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081329 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521330 # If actions.xml is already included in the changelist, the PRESUBMIT
1331 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081332 return []
1333
[email protected]999261d2014-03-03 20:08:081334 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1335 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521336 current_actions = None
[email protected]999261d2014-03-03 20:08:081337 for f in input_api.AffectedFiles(file_filter=file_filter):
1338 for line_num, line in f.ChangedContents():
1339 match = input_api.re.search(action_re, line)
1340 if match:
[email protected]2f92dec2014-03-07 19:21:521341 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1342 # loaded only once.
1343 if not current_actions:
1344 with open('tools/metrics/actions/actions.xml') as actions_f:
1345 current_actions = actions_f.read()
1346 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081347 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521348 action = 'name="{0}"'.format(action_name)
1349 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081350 return [output_api.PresubmitPromptWarning(
1351 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521352 'tools/metrics/actions/actions.xml. Please run '
1353 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081354 % (f.LocalPath(), line_num, action_name))]
1355 return []
1356
1357
Daniel Cheng13ca61a882017-08-25 15:11:251358def _ImportJSONCommentEater(input_api):
1359 import sys
1360 sys.path = sys.path + [input_api.os_path.join(
1361 input_api.PresubmitLocalPath(),
1362 'tools', 'json_comment_eater')]
1363 import json_comment_eater
1364 return json_comment_eater
1365
1366
[email protected]99171a92014-06-03 08:44:471367def _GetJSONParseError(input_api, filename, eat_comments=True):
1368 try:
1369 contents = input_api.ReadFile(filename)
1370 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:251371 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:131372 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471373
1374 input_api.json.loads(contents)
1375 except ValueError as e:
1376 return e
1377 return None
1378
1379
1380def _GetIDLParseError(input_api, filename):
1381 try:
1382 contents = input_api.ReadFile(filename)
1383 idl_schema = input_api.os_path.join(
1384 input_api.PresubmitLocalPath(),
1385 'tools', 'json_schema_compiler', 'idl_schema.py')
1386 process = input_api.subprocess.Popen(
1387 [input_api.python_executable, idl_schema],
1388 stdin=input_api.subprocess.PIPE,
1389 stdout=input_api.subprocess.PIPE,
1390 stderr=input_api.subprocess.PIPE,
1391 universal_newlines=True)
1392 (_, error) = process.communicate(input=contents)
1393 return error or None
1394 except ValueError as e:
1395 return e
1396
1397
1398def _CheckParseErrors(input_api, output_api):
1399 """Check that IDL and JSON files do not contain syntax errors."""
1400 actions = {
1401 '.idl': _GetIDLParseError,
1402 '.json': _GetJSONParseError,
1403 }
[email protected]99171a92014-06-03 08:44:471404 # Most JSON files are preprocessed and support comments, but these do not.
1405 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491406 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471407 ]
1408 # Only run IDL checker on files in these directories.
1409 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491410 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1411 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471412 ]
1413
1414 def get_action(affected_file):
1415 filename = affected_file.LocalPath()
1416 return actions.get(input_api.os_path.splitext(filename)[1])
1417
[email protected]99171a92014-06-03 08:44:471418 def FilterFile(affected_file):
1419 action = get_action(affected_file)
1420 if not action:
1421 return False
1422 path = affected_file.LocalPath()
1423
Sean Kau46e29bc2017-08-28 16:31:161424 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:471425 return False
1426
1427 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:161428 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:471429 return False
1430 return True
1431
1432 results = []
1433 for affected_file in input_api.AffectedFiles(
1434 file_filter=FilterFile, include_deletes=False):
1435 action = get_action(affected_file)
1436 kwargs = {}
1437 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:161438 _MatchesFile(input_api, json_no_comments_patterns,
1439 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:471440 kwargs['eat_comments'] = False
1441 parse_error = action(input_api,
1442 affected_file.AbsoluteLocalPath(),
1443 **kwargs)
1444 if parse_error:
1445 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1446 (affected_file.LocalPath(), parse_error)))
1447 return results
1448
1449
[email protected]760deea2013-12-10 19:33:491450def _CheckJavaStyle(input_api, output_api):
1451 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471452 import sys
[email protected]760deea2013-12-10 19:33:491453 original_sys_path = sys.path
1454 try:
1455 sys.path = sys.path + [input_api.os_path.join(
1456 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1457 import checkstyle
1458 finally:
1459 # Restore sys.path to what it was before.
1460 sys.path = original_sys_path
1461
1462 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091463 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511464 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491465
1466
Sean Kau46e29bc2017-08-28 16:31:161467def _MatchesFile(input_api, patterns, path):
1468 for pattern in patterns:
1469 if input_api.re.search(pattern, path):
1470 return True
1471 return False
1472
1473
dchenge07de812016-06-20 19:27:171474def _CheckIpcOwners(input_api, output_api):
1475 """Checks that affected files involving IPC have an IPC OWNERS rule.
1476
1477 Whether or not a file affects IPC is determined by a simple whitelist of
1478 filename patterns."""
1479 file_patterns = [
palmerb19a0932017-01-24 04:00:311480 # Legacy IPC:
dchenge07de812016-06-20 19:27:171481 '*_messages.cc',
1482 '*_messages*.h',
1483 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311484 # Mojo IPC:
dchenge07de812016-06-20 19:27:171485 '*.mojom',
1486 '*_struct_traits*.*',
1487 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311488 '*.typemap',
1489 # Android native IPC:
1490 '*.aidl',
1491 # Blink uses a different file naming convention:
1492 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171493 '*StructTraits*.*',
1494 '*TypeConverter*.*',
1495 ]
1496
scottmg7a6ed5ba2016-11-04 18:22:041497 # These third_party directories do not contain IPCs, but contain files
1498 # matching the above patterns, which trigger false positives.
1499 exclude_paths = [
1500 'third_party/crashpad/*',
1501 ]
1502
dchenge07de812016-06-20 19:27:171503 # Dictionary mapping an OWNERS file path to Patterns.
1504 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1505 # rules ) to a PatternEntry.
1506 # PatternEntry is a dictionary with two keys:
1507 # - 'files': the files that are matched by this pattern
1508 # - 'rules': the per-file rules needed for this pattern
1509 # For example, if we expect OWNERS file to contain rules for *.mojom and
1510 # *_struct_traits*.*, Patterns might look like this:
1511 # {
1512 # '*.mojom': {
1513 # 'files': ...,
1514 # 'rules': [
1515 # 'per-file *.mojom=set noparent',
1516 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1517 # ],
1518 # },
1519 # '*_struct_traits*.*': {
1520 # 'files': ...,
1521 # 'rules': [
1522 # 'per-file *_struct_traits*.*=set noparent',
1523 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1524 # ],
1525 # },
1526 # }
1527 to_check = {}
1528
Daniel Cheng13ca61a882017-08-25 15:11:251529 def AddPatternToCheck(input_file, pattern):
1530 owners_file = input_api.os_path.join(
1531 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
1532 if owners_file not in to_check:
1533 to_check[owners_file] = {}
1534 if pattern not in to_check[owners_file]:
1535 to_check[owners_file][pattern] = {
1536 'files': [],
1537 'rules': [
1538 'per-file %s=set noparent' % pattern,
1539 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1540 ]
1541 }
1542 to_check[owners_file][pattern]['files'].append(f)
1543
dchenge07de812016-06-20 19:27:171544 # Iterate through the affected files to see what we actually need to check
1545 # for. We should only nag patch authors about per-file rules if a file in that
1546 # directory would match that pattern. If a directory only contains *.mojom
1547 # files and no *_messages*.h files, we should only nag about rules for
1548 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:251549 for f in input_api.AffectedFiles(include_deletes=False):
1550 # Manifest files don't have a strong naming convention. Instead, scan
1551 # affected files for .json files and see if they look like a manifest.
Sean Kau46e29bc2017-08-28 16:31:161552 if (f.LocalPath().endswith('.json') and
1553 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
1554 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:251555 json_comment_eater = _ImportJSONCommentEater(input_api)
1556 mostly_json_lines = '\n'.join(f.NewContents())
1557 # Comments aren't allowed in strict JSON, so filter them out.
1558 json_lines = json_comment_eater.Nom(mostly_json_lines)
1559 json_content = input_api.json.loads(json_lines)
1560 if 'interface_provider_specs' in json_content:
1561 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:171562 for pattern in file_patterns:
1563 if input_api.fnmatch.fnmatch(
1564 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041565 skip = False
1566 for exclude in exclude_paths:
1567 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1568 skip = True
1569 break
1570 if skip:
1571 continue
Daniel Cheng13ca61a882017-08-25 15:11:251572 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:171573 break
1574
1575 # Now go through the OWNERS files we collected, filtering out rules that are
1576 # already present in that OWNERS file.
1577 for owners_file, patterns in to_check.iteritems():
1578 try:
1579 with file(owners_file) as f:
1580 lines = set(f.read().splitlines())
1581 for entry in patterns.itervalues():
1582 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1583 ]
1584 except IOError:
1585 # No OWNERS file, so all the rules are definitely missing.
1586 continue
1587
1588 # All the remaining lines weren't found in OWNERS files, so emit an error.
1589 errors = []
1590 for owners_file, patterns in to_check.iteritems():
1591 missing_lines = []
1592 files = []
1593 for pattern, entry in patterns.iteritems():
1594 missing_lines.extend(entry['rules'])
1595 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1596 if missing_lines:
1597 errors.append(
Daniel Cheng52111692017-06-14 08:00:591598 '%s needs the following lines added:\n\n%s\n\nfor files:\n%s' %
dchenge07de812016-06-20 19:27:171599 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1600
1601 results = []
1602 if errors:
vabrf5ce3bf92016-07-11 14:52:411603 if input_api.is_committing:
1604 output = output_api.PresubmitError
1605 else:
1606 output = output_api.PresubmitPromptWarning
1607 results.append(output(
Daniel Cheng52111692017-06-14 08:00:591608 'Found OWNERS files that need to be updated for IPC security ' +
1609 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:171610 long_text='\n\n'.join(errors)))
1611
1612 return results
1613
1614
jbriance9e12f162016-11-25 07:57:501615def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311616 """Checks that added or removed lines in non third party affected
1617 header files do not lead to new useless class or struct forward
1618 declaration.
jbriance9e12f162016-11-25 07:57:501619 """
1620 results = []
1621 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1622 input_api.re.MULTILINE)
1623 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1624 input_api.re.MULTILINE)
1625 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311626 if (f.LocalPath().startswith('third_party') and
1627 not f.LocalPath().startswith('third_party/WebKit') and
1628 not f.LocalPath().startswith('third_party\\WebKit')):
1629 continue
1630
jbriance9e12f162016-11-25 07:57:501631 if not f.LocalPath().endswith('.h'):
1632 continue
1633
1634 contents = input_api.ReadFile(f)
1635 fwd_decls = input_api.re.findall(class_pattern, contents)
1636 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1637
1638 useless_fwd_decls = []
1639 for decl in fwd_decls:
1640 count = sum(1 for _ in input_api.re.finditer(
1641 r'\b%s\b' % input_api.re.escape(decl), contents))
1642 if count == 1:
1643 useless_fwd_decls.append(decl)
1644
1645 if not useless_fwd_decls:
1646 continue
1647
1648 for line in f.GenerateScmDiff().splitlines():
1649 if (line.startswith('-') and not line.startswith('--') or
1650 line.startswith('+') and not line.startswith('++')):
1651 for decl in useless_fwd_decls:
1652 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1653 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:241654 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:501655 (f.LocalPath(), decl)))
1656 useless_fwd_decls.remove(decl)
1657
1658 return results
1659
1660
dskiba88634f4e2015-08-14 23:03:291661def _CheckAndroidToastUsage(input_api, output_api):
1662 """Checks that code uses org.chromium.ui.widget.Toast instead of
1663 android.widget.Toast (Chromium Toast doesn't force hardware
1664 acceleration on low-end devices, saving memory).
1665 """
1666 toast_import_pattern = input_api.re.compile(
1667 r'^import android\.widget\.Toast;$')
1668
1669 errors = []
1670
1671 sources = lambda affected_file: input_api.FilterSourceFile(
1672 affected_file,
1673 black_list=(_EXCLUDED_PATHS +
1674 _TEST_CODE_EXCLUDED_PATHS +
1675 input_api.DEFAULT_BLACK_LIST +
1676 (r'^chromecast[\\\/].*',
1677 r'^remoting[\\\/].*')),
1678 white_list=(r'.*\.java$',))
1679
1680 for f in input_api.AffectedSourceFiles(sources):
1681 for line_num, line in f.ChangedContents():
1682 if toast_import_pattern.search(line):
1683 errors.append("%s:%d" % (f.LocalPath(), line_num))
1684
1685 results = []
1686
1687 if errors:
1688 results.append(output_api.PresubmitError(
1689 'android.widget.Toast usage is detected. Android toasts use hardware'
1690 ' acceleration, and can be\ncostly on low-end devices. Please use'
1691 ' org.chromium.ui.widget.Toast instead.\n'
1692 'Contact [email protected] if you have any questions.',
1693 errors))
1694
1695 return results
1696
1697
dgnaa68d5e2015-06-10 10:08:221698def _CheckAndroidCrLogUsage(input_api, output_api):
1699 """Checks that new logs using org.chromium.base.Log:
1700 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511701 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221702 """
pkotwicza1dd0b002016-05-16 14:41:041703
torne89540622017-03-24 19:41:301704 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041705 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301706 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041707 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301708 # WebView license viewer code cannot depend on //base; used in stub APK.
1709 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1710 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041711 ]
1712
dgnaa68d5e2015-06-10 10:08:221713 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121714 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1715 class_in_base_pattern = input_api.re.compile(
1716 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1717 has_some_log_import_pattern = input_api.re.compile(
1718 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221719 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121720 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221721 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511722 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221723 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221724
Vincent Scheib16d7b272015-09-15 18:09:071725 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221726 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041727 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1728 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121729
dgnaa68d5e2015-06-10 10:08:221730 tag_decl_errors = []
1731 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121732 tag_errors = []
dgn38736db2015-09-18 19:20:511733 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121734 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221735
1736 for f in input_api.AffectedSourceFiles(sources):
1737 file_content = input_api.ReadFile(f)
1738 has_modified_logs = False
1739
1740 # Per line checks
dgn87d9fb62015-06-12 09:15:121741 if (cr_log_import_pattern.search(file_content) or
1742 (class_in_base_pattern.search(file_content) and
1743 not has_some_log_import_pattern.search(file_content))):
1744 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221745 for line_num, line in f.ChangedContents():
1746
1747 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121748 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221749 if match:
1750 has_modified_logs = True
1751
1752 # Make sure it uses "TAG"
1753 if not match.group('tag') == 'TAG':
1754 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121755 else:
1756 # Report non cr Log function calls in changed lines
1757 for line_num, line in f.ChangedContents():
1758 if log_call_pattern.search(line):
1759 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221760
1761 # Per file checks
1762 if has_modified_logs:
1763 # Make sure the tag is using the "cr" prefix and is not too long
1764 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511765 tag_name = match.group('name') if match else None
1766 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221767 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511768 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221769 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511770 elif '.' in tag_name:
1771 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221772
1773 results = []
1774 if tag_decl_errors:
1775 results.append(output_api.PresubmitPromptWarning(
1776 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511777 '"private static final String TAG = "<package tag>".\n'
1778 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221779 tag_decl_errors))
1780
1781 if tag_length_errors:
1782 results.append(output_api.PresubmitError(
1783 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511784 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221785 tag_length_errors))
1786
1787 if tag_errors:
1788 results.append(output_api.PresubmitPromptWarning(
1789 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1790 tag_errors))
1791
dgn87d9fb62015-06-12 09:15:121792 if util_log_errors:
dgn4401aa52015-04-29 16:26:171793 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121794 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1795 util_log_errors))
1796
dgn38736db2015-09-18 19:20:511797 if tag_with_dot_errors:
1798 results.append(output_api.PresubmitPromptWarning(
1799 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1800 tag_with_dot_errors))
1801
dgn4401aa52015-04-29 16:26:171802 return results
1803
1804
Yoland Yanb92fa522017-08-28 17:37:061805def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
1806 """Checks that junit.framework.* is no longer used."""
1807 deprecated_junit_framework_pattern = input_api.re.compile(
1808 r'^import junit\.framework\..*;',
1809 input_api.re.MULTILINE)
1810 sources = lambda x: input_api.FilterSourceFile(
1811 x, white_list=(r'.*\.java$',), black_list=None)
1812 errors = []
1813 for f in input_api.AffectedFiles(sources):
1814 for line_num, line in f.ChangedContents():
1815 if deprecated_junit_framework_pattern.search(line):
1816 errors.append("%s:%d" % (f.LocalPath(), line_num))
1817
1818 results = []
1819 if errors:
1820 results.append(output_api.PresubmitError(
1821 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
1822 '(org.junit.*) from //third_party/junit. Contact [email protected]'
1823 ' if you have any question.', errors))
1824 return results
1825
1826
1827def _CheckAndroidTestJUnitInheritance(input_api, output_api):
1828 """Checks that if new Java test classes have inheritance.
1829 Either the new test class is JUnit3 test or it is a JUnit4 test class
1830 with a base class, either case is undesirable.
1831 """
1832 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
1833
1834 sources = lambda x: input_api.FilterSourceFile(
1835 x, white_list=(r'.*Test\.java$',), black_list=None)
1836 errors = []
1837 for f in input_api.AffectedFiles(sources):
1838 if not f.OldContents():
1839 class_declaration_start_flag = False
1840 for line_num, line in f.ChangedContents():
1841 if class_declaration_pattern.search(line):
1842 class_declaration_start_flag = True
1843 if class_declaration_start_flag and ' extends ' in line:
1844 errors.append('%s:%d' % (f.LocalPath(), line_num))
1845 if '{' in line:
1846 class_declaration_start_flag = False
1847
1848 results = []
1849 if errors:
1850 results.append(output_api.PresubmitPromptWarning(
1851 'The newly created files include Test classes that inherits from base'
1852 ' class. Please do not use inheritance in JUnit4 tests or add new'
1853 ' JUnit3 tests. Contact [email protected] if you have any'
1854 ' questions.', errors))
1855 return results
1856
yolandyan45001472016-12-21 21:12:421857def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1858 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1859 deprecated_annotation_import_pattern = input_api.re.compile(
1860 r'^import android\.test\.suitebuilder\.annotation\..*;',
1861 input_api.re.MULTILINE)
1862 sources = lambda x: input_api.FilterSourceFile(
1863 x, white_list=(r'.*\.java$',), black_list=None)
1864 errors = []
1865 for f in input_api.AffectedFiles(sources):
1866 for line_num, line in f.ChangedContents():
1867 if deprecated_annotation_import_pattern.search(line):
1868 errors.append("%s:%d" % (f.LocalPath(), line_num))
1869
1870 results = []
1871 if errors:
1872 results.append(output_api.PresubmitError(
1873 'Annotations in android.test.suitebuilder.annotation have been'
1874 ' deprecated since API level 24. Please use android.support.test.filters'
1875 ' from //third_party/android_support_test_runner:runner_java instead.'
1876 ' Contact [email protected] if you have any questions.', errors))
1877 return results
1878
1879
agrieve7b6479d82015-10-07 14:24:221880def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1881 """Checks if MDPI assets are placed in a correct directory."""
1882 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1883 ('/res/drawable/' in f.LocalPath() or
1884 '/res/drawable-ldrtl/' in f.LocalPath()))
1885 errors = []
1886 for f in input_api.AffectedFiles(include_deletes=False,
1887 file_filter=file_filter):
1888 errors.append(' %s' % f.LocalPath())
1889
1890 results = []
1891 if errors:
1892 results.append(output_api.PresubmitError(
1893 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1894 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1895 '/res/drawable-ldrtl/.\n'
1896 'Contact [email protected] if you have questions.', errors))
1897 return results
1898
1899
agrievef32bcc72016-04-04 14:57:401900class PydepsChecker(object):
1901 def __init__(self, input_api, pydeps_files):
1902 self._file_cache = {}
1903 self._input_api = input_api
1904 self._pydeps_files = pydeps_files
1905
1906 def _LoadFile(self, path):
1907 """Returns the list of paths within a .pydeps file relative to //."""
1908 if path not in self._file_cache:
1909 with open(path) as f:
1910 self._file_cache[path] = f.read()
1911 return self._file_cache[path]
1912
1913 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1914 """Returns an interable of paths within the .pydep, relativized to //."""
1915 os_path = self._input_api.os_path
1916 pydeps_dir = os_path.dirname(pydeps_path)
1917 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1918 if not l.startswith('*'))
1919 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1920
1921 def _CreateFilesToPydepsMap(self):
1922 """Returns a map of local_path -> list_of_pydeps."""
1923 ret = {}
1924 for pydep_local_path in self._pydeps_files:
1925 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1926 ret.setdefault(path, []).append(pydep_local_path)
1927 return ret
1928
1929 def ComputeAffectedPydeps(self):
1930 """Returns an iterable of .pydeps files that might need regenerating."""
1931 affected_pydeps = set()
1932 file_to_pydeps_map = None
1933 for f in self._input_api.AffectedFiles(include_deletes=True):
1934 local_path = f.LocalPath()
1935 if local_path == 'DEPS':
1936 return self._pydeps_files
1937 elif local_path.endswith('.pydeps'):
1938 if local_path in self._pydeps_files:
1939 affected_pydeps.add(local_path)
1940 elif local_path.endswith('.py'):
1941 if file_to_pydeps_map is None:
1942 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1943 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1944 return affected_pydeps
1945
1946 def DetermineIfStale(self, pydeps_path):
1947 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411948 import difflib
agrievef32bcc72016-04-04 14:57:401949 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1950 cmd = old_pydeps_data[1][1:].strip()
1951 new_pydeps_data = self._input_api.subprocess.check_output(
1952 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411953 old_contents = old_pydeps_data[2:]
1954 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401955 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411956 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401957
1958
1959def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1960 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001961 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281962 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1963 # Mac, so skip it on other platforms.
1964 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001965 return []
agrievef32bcc72016-04-04 14:57:401966 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1967 is_android = input_api.os_path.exists('third_party/android_tools')
1968 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1969 results = []
1970 # First, check for new / deleted .pydeps.
1971 for f in input_api.AffectedFiles(include_deletes=True):
1972 if f.LocalPath().endswith('.pydeps'):
1973 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1974 results.append(output_api.PresubmitError(
1975 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1976 'remove %s' % f.LocalPath()))
1977 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1978 results.append(output_api.PresubmitError(
1979 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1980 'include %s' % f.LocalPath()))
1981
1982 if results:
1983 return results
1984
1985 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1986
1987 for pydep_path in checker.ComputeAffectedPydeps():
1988 try:
phajdan.jr0d9878552016-11-04 10:49:411989 result = checker.DetermineIfStale(pydep_path)
1990 if result:
1991 cmd, diff = result
agrievef32bcc72016-04-04 14:57:401992 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:411993 'File is stale: %s\nDiff (apply to fix):\n%s\n'
1994 'To regenerate, run:\n\n %s' %
1995 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:401996 except input_api.subprocess.CalledProcessError as error:
1997 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1998 long_text=error.output)]
1999
2000 return results
2001
2002
glidere61efad2015-02-18 17:39:432003def _CheckSingletonInHeaders(input_api, output_api):
2004 """Checks to make sure no header files have |Singleton<|."""
2005 def FileFilter(affected_file):
2006 # It's ok for base/memory/singleton.h to have |Singleton<|.
2007 black_list = (_EXCLUDED_PATHS +
2008 input_api.DEFAULT_BLACK_LIST +
2009 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
2010 return input_api.FilterSourceFile(affected_file, black_list=black_list)
2011
sergeyu34d21222015-09-16 00:11:442012 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:432013 files = []
2014 for f in input_api.AffectedSourceFiles(FileFilter):
2015 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
2016 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
2017 contents = input_api.ReadFile(f)
2018 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:242019 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:432020 pattern.search(line)):
2021 files.append(f)
2022 break
2023
2024 if files:
yolandyandaabc6d2016-04-18 18:29:392025 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:442026 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:432027 'Please move them to an appropriate source file so that the ' +
2028 'template gets instantiated in a single compilation unit.',
2029 files) ]
2030 return []
2031
2032
[email protected]fd20b902014-05-09 02:14:532033_DEPRECATED_CSS = [
2034 # Values
2035 ( "-webkit-box", "flex" ),
2036 ( "-webkit-inline-box", "inline-flex" ),
2037 ( "-webkit-flex", "flex" ),
2038 ( "-webkit-inline-flex", "inline-flex" ),
2039 ( "-webkit-min-content", "min-content" ),
2040 ( "-webkit-max-content", "max-content" ),
2041
2042 # Properties
2043 ( "-webkit-background-clip", "background-clip" ),
2044 ( "-webkit-background-origin", "background-origin" ),
2045 ( "-webkit-background-size", "background-size" ),
2046 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442047 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532048
2049 # Functions
2050 ( "-webkit-gradient", "gradient" ),
2051 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2052 ( "-webkit-linear-gradient", "linear-gradient" ),
2053 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2054 ( "-webkit-radial-gradient", "radial-gradient" ),
2055 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2056]
2057
dbeam1ec68ac2016-12-15 05:22:242058def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532059 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252060 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342061 documentation and iOS CSS for dom distiller
2062 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252063 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532064 results = []
dbeam070cfe62014-10-22 06:44:022065 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252066 black_list = (_EXCLUDED_PATHS +
2067 _TEST_CODE_EXCLUDED_PATHS +
2068 input_api.DEFAULT_BLACK_LIST +
2069 (r"^chrome/common/extensions/docs",
2070 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342071 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:442072 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252073 r"^native_client_sdk"))
2074 file_filter = lambda f: input_api.FilterSourceFile(
2075 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532076 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2077 for line_num, line in fpath.ChangedContents():
2078 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022079 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532080 results.append(output_api.PresubmitError(
2081 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2082 (fpath.LocalPath(), line_num, deprecated_value, value)))
2083 return results
2084
mohan.reddyf21db962014-10-16 12:26:472085
dbeam070cfe62014-10-22 06:44:022086_DEPRECATED_JS = [
2087 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2088 ( "__defineGetter__", "Object.defineProperty" ),
2089 ( "__defineSetter__", "Object.defineProperty" ),
2090]
2091
dbeam1ec68ac2016-12-15 05:22:242092def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022093 """Make sure that we don't use deprecated JS in Chrome code."""
2094 results = []
2095 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2096 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2097 input_api.DEFAULT_BLACK_LIST)
2098 file_filter = lambda f: input_api.FilterSourceFile(
2099 f, white_list=file_inclusion_pattern, black_list=black_list)
2100 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2101 for lnum, line in fpath.ChangedContents():
2102 for (deprecated, replacement) in _DEPRECATED_JS:
2103 if deprecated in line:
2104 results.append(output_api.PresubmitError(
2105 "%s:%d: Use of deprecated JS %s, use %s instead" %
2106 (fpath.LocalPath(), lnum, deprecated, replacement)))
2107 return results
2108
dpapadd651231d82017-07-21 02:44:472109def _CheckForRiskyJsArrowFunction(line_number, line):
2110 if ' => ' in line:
2111 return "line %d, is using an => (arrow) function\n %s\n" % (
2112 line_number, line)
2113 return ''
2114
2115def _CheckForRiskyJsConstLet(input_api, line_number, line):
2116 if input_api.re.match('^\s*(const|let)\s', line):
2117 return "line %d, is using const/let keyword\n %s\n" % (
2118 line_number, line)
2119 return ''
dbeam070cfe62014-10-22 06:44:022120
dbeam1ec68ac2016-12-15 05:22:242121def _CheckForRiskyJsFeatures(input_api, output_api):
2122 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
Steven Bennetts90545f3cb2017-08-14 18:11:002123 # 'ui/webui/resources/cr_components are not allowed on ios'
2124 not_ios_filter = (r".*ui\/webui\/resources\/cr_components.*", )
Steven Bennetts9c7e3c22017-08-02 19:10:572125 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
Steven Bennetts90545f3cb2017-08-14 18:11:002126 black_list=not_ios_filter)
dpapadd651231d82017-07-21 02:44:472127 results = []
dbeam1ec68ac2016-12-15 05:22:242128 for f in input_api.AffectedFiles(file_filter=file_filter):
dpapadd651231d82017-07-21 02:44:472129 arrow_error_lines = []
2130 const_let_error_lines = []
dbeam1ec68ac2016-12-15 05:22:242131 for lnum, line in f.ChangedContents():
dpapadd651231d82017-07-21 02:44:472132 arrow_error_lines += filter(None, [
2133 _CheckForRiskyJsArrowFunction(lnum, line),
2134 ])
dbeam1ec68ac2016-12-15 05:22:242135
dpapadd651231d82017-07-21 02:44:472136 const_let_error_lines += filter(None, [
2137 _CheckForRiskyJsConstLet(input_api, lnum, line),
2138 ])
dbeam1ec68ac2016-12-15 05:22:242139
dpapadd651231d82017-07-21 02:44:472140 if arrow_error_lines:
2141 arrow_error_lines = map(
2142 lambda e: "%s:%s" % (f.LocalPath(), e), arrow_error_lines)
2143 results.append(
2144 output_api.PresubmitPromptWarning('\n'.join(arrow_error_lines + [
2145"""
2146Use of => (arrow) operator detected in:
dbeam1ec68ac2016-12-15 05:22:242147%s
2148Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2149https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
dpapadd651231d82017-07-21 02:44:472150""" % f.LocalPath()
2151 ])))
dbeam1ec68ac2016-12-15 05:22:242152
dpapadd651231d82017-07-21 02:44:472153 if const_let_error_lines:
2154 const_let_error_lines = map(
2155 lambda e: "%s:%s" % (f.LocalPath(), e), const_let_error_lines)
2156 results.append(
2157 output_api.PresubmitPromptWarning('\n'.join(const_let_error_lines + [
2158"""
2159Use of const/let keywords detected in:
2160%s
2161Please ensure your code does not run on iOS9 because const/let is not fully
2162supported.
2163https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables
2164https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants
2165""" % f.LocalPath()
2166 ])))
2167
2168 return results
dbeam1ec68ac2016-12-15 05:22:242169
rlanday6802cf632017-05-30 17:48:362170def _CheckForRelativeIncludes(input_api, output_api):
2171 # Need to set the sys.path so PRESUBMIT_test.py runs properly
2172 import sys
2173 original_sys_path = sys.path
2174 try:
2175 sys.path = sys.path + [input_api.os_path.join(
2176 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
2177 from cpp_checker import CppChecker
2178 finally:
2179 # Restore sys.path to what it was before.
2180 sys.path = original_sys_path
2181
2182 bad_files = {}
2183 for f in input_api.AffectedFiles(include_deletes=False):
2184 if (f.LocalPath().startswith('third_party') and
2185 not f.LocalPath().startswith('third_party/WebKit') and
2186 not f.LocalPath().startswith('third_party\\WebKit')):
2187 continue
2188
2189 if not CppChecker.IsCppFile(f.LocalPath()):
2190 continue
2191
2192 relative_includes = [line for line_num, line in f.ChangedContents()
2193 if "#include" in line and "../" in line]
2194 if not relative_includes:
2195 continue
2196 bad_files[f.LocalPath()] = relative_includes
2197
2198 if not bad_files:
2199 return []
2200
2201 error_descriptions = []
2202 for file_path, bad_lines in bad_files.iteritems():
2203 error_description = file_path
2204 for line in bad_lines:
2205 error_description += '\n ' + line
2206 error_descriptions.append(error_description)
2207
2208 results = []
2209 results.append(output_api.PresubmitError(
2210 'You added one or more relative #include paths (including "../").\n'
2211 'These shouldn\'t be used because they can be used to include headers\n'
2212 'from code that\'s not correctly specified as a dependency in the\n'
2213 'relevant BUILD.gn file(s).',
2214 error_descriptions))
2215
2216 return results
2217
Takeshi Yoshinoe387aa32017-08-02 13:16:132218
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202219def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
2220 if not isinstance(key, ast.Str):
2221 return 'Key at line %d must be a string literal' % key.lineno
2222 if not isinstance(value, ast.Dict):
2223 return 'Value at line %d must be a dict' % value.lineno
2224 if len(value.keys) != 1:
2225 return 'Dict at line %d must have single entry' % value.lineno
2226 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
2227 return (
2228 'Entry at line %d must have a string literal \'filepath\' as key' %
2229 value.lineno)
2230 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132231
Takeshi Yoshinoe387aa32017-08-02 13:16:132232
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202233def _CheckWatchlistsEntrySyntax(key, value, ast):
2234 if not isinstance(key, ast.Str):
2235 return 'Key at line %d must be a string literal' % key.lineno
2236 if not isinstance(value, ast.List):
2237 return 'Value at line %d must be a list' % value.lineno
2238 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:132239
Takeshi Yoshinoe387aa32017-08-02 13:16:132240
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202241def _CheckWATCHLISTSEntries(wd_dict, w_dict, ast):
2242 mismatch_template = (
2243 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
2244 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:132245
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202246 i = 0
2247 last_key = ''
2248 while True:
2249 if i >= len(wd_dict.keys):
2250 if i >= len(w_dict.keys):
2251 return None
2252 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
2253 elif i >= len(w_dict.keys):
2254 return (
2255 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:132256
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202257 wd_key = wd_dict.keys[i]
2258 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:132259
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202260 result = _CheckWatchlistDefinitionsEntrySyntax(
2261 wd_key, wd_dict.values[i], ast)
2262 if result is not None:
2263 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:132264
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202265 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast)
2266 if result is not None:
2267 return 'Bad entry in WATCHLISTS dict: %s' % result
2268
2269 if wd_key.s != w_key.s:
2270 return mismatch_template % (
2271 '%s at line %d' % (wd_key.s, wd_key.lineno),
2272 '%s at line %d' % (w_key.s, w_key.lineno))
2273
2274 if wd_key.s < last_key:
2275 return (
2276 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
2277 (wd_key.lineno, w_key.lineno))
2278 last_key = wd_key.s
2279
2280 i = i + 1
2281
2282
2283def _CheckWATCHLISTSSyntax(expression, ast):
2284 if not isinstance(expression, ast.Expression):
2285 return 'WATCHLISTS file must contain a valid expression'
2286 dictionary = expression.body
2287 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
2288 return 'WATCHLISTS file must have single dict with exactly two entries'
2289
2290 first_key = dictionary.keys[0]
2291 first_value = dictionary.values[0]
2292 second_key = dictionary.keys[1]
2293 second_value = dictionary.values[1]
2294
2295 if (not isinstance(first_key, ast.Str) or
2296 first_key.s != 'WATCHLIST_DEFINITIONS' or
2297 not isinstance(first_value, ast.Dict)):
2298 return (
2299 'The first entry of the dict in WATCHLISTS file must be '
2300 'WATCHLIST_DEFINITIONS dict')
2301
2302 if (not isinstance(second_key, ast.Str) or
2303 second_key.s != 'WATCHLISTS' or
2304 not isinstance(second_value, ast.Dict)):
2305 return (
2306 'The second entry of the dict in WATCHLISTS file must be '
2307 'WATCHLISTS dict')
2308
2309 return _CheckWATCHLISTSEntries(first_value, second_value, ast)
Takeshi Yoshinoe387aa32017-08-02 13:16:132310
2311
2312def _CheckWATCHLISTS(input_api, output_api):
2313 for f in input_api.AffectedFiles(include_deletes=False):
2314 if f.LocalPath() == 'WATCHLISTS':
2315 contents = input_api.ReadFile(f, 'r')
2316
2317 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202318 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:132319 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202320 # Get an AST tree for it and scan the tree for detailed style checking.
2321 expression = input_api.ast.parse(
2322 contents, filename='WATCHLISTS', mode='eval')
2323 except ValueError as e:
2324 return [output_api.PresubmitError(
2325 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2326 except SyntaxError as e:
2327 return [output_api.PresubmitError(
2328 'Cannot parse WATCHLISTS file', long_text=repr(e))]
2329 except TypeError as e:
2330 return [output_api.PresubmitError(
2331 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:132332
Takeshi Yoshino3a8f9cb52017-08-10 11:32:202333 result = _CheckWATCHLISTSSyntax(expression, input_api.ast)
2334 if result is not None:
2335 return [output_api.PresubmitError(result)]
2336 break
Takeshi Yoshinoe387aa32017-08-02 13:16:132337
2338 return []
2339
2340
dgnaa68d5e2015-06-10 10:08:222341def _AndroidSpecificOnUploadChecks(input_api, output_api):
2342 """Groups checks that target android code."""
2343 results = []
dgnaa68d5e2015-06-10 10:08:222344 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222345 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292346 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:062347 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
2348 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:422349 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222350 return results
2351
2352
[email protected]22c9bd72011-03-27 16:47:392353def _CommonChecks(input_api, output_api):
2354 """Checks common to both upload and commit."""
2355 results = []
2356 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382357 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542358 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582359 results.extend(
2360 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192361 results.extend(
[email protected]760deea2013-12-10 19:33:492362 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542363 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182364 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522365 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222366 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442367 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592368 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062369 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122370 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182371 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222372 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302373 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492374 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032375 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492376 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442377 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272378 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:072379 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542380 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442381 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392382 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552383 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042384 results.extend(
2385 input_api.canned_checks.CheckChangeHasNoTabs(
2386 input_api,
2387 output_api,
2388 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402389 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162390 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082391 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242392 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2393 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472394 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042395 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232396 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432397 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402398 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152399 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172400 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502401 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242402 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
rlanday6802cf632017-05-30 17:48:362403 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:132404 results.extend(_CheckWATCHLISTS(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242405
2406 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2407 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2408 input_api, output_api,
2409 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382410 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392411 return results
[email protected]1f7b4172010-01-28 01:17:342412
[email protected]b337cb5b2011-01-23 21:24:052413
[email protected]b8079ae4a2012-12-05 19:56:492414def _CheckPatchFiles(input_api, output_api):
2415 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2416 if f.LocalPath().endswith(('.orig', '.rej'))]
2417 if problems:
2418 return [output_api.PresubmitError(
2419 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032420 else:
2421 return []
[email protected]b8079ae4a2012-12-05 19:56:492422
2423
Kent Tamura5a8755d2017-06-29 23:37:072424def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:212425 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
2426 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
2427 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:072428 include_re = input_api.re.compile(
2429 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
2430 extension_re = input_api.re.compile(r'\.[a-z]+$')
2431 errors = []
2432 for f in input_api.AffectedFiles():
2433 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
2434 continue
2435 found_line_number = None
2436 found_macro = None
2437 for line_num, line in f.ChangedContents():
2438 match = macro_re.search(line)
2439 if match:
2440 found_line_number = line_num
2441 found_macro = match.group(2)
2442 break
2443 if not found_line_number:
2444 continue
2445
2446 found_include = False
2447 for line in f.NewContents():
2448 if include_re.search(line):
2449 found_include = True
2450 break
2451 if found_include:
2452 continue
2453
2454 if not f.LocalPath().endswith('.h'):
2455 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
2456 try:
2457 content = input_api.ReadFile(primary_header_path, 'r')
2458 if include_re.search(content):
2459 continue
2460 except IOError:
2461 pass
2462 errors.append('%s:%d %s macro is used without including build/'
2463 'build_config.h.'
2464 % (f.LocalPath(), found_line_number, found_macro))
2465 if errors:
2466 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
2467 return []
2468
2469
[email protected]b00342e7f2013-03-26 16:21:542470def _DidYouMeanOSMacro(bad_macro):
2471 try:
2472 return {'A': 'OS_ANDROID',
2473 'B': 'OS_BSD',
2474 'C': 'OS_CHROMEOS',
2475 'F': 'OS_FREEBSD',
2476 'L': 'OS_LINUX',
2477 'M': 'OS_MACOSX',
2478 'N': 'OS_NACL',
2479 'O': 'OS_OPENBSD',
2480 'P': 'OS_POSIX',
2481 'S': 'OS_SOLARIS',
2482 'W': 'OS_WIN'}[bad_macro[3].upper()]
2483 except KeyError:
2484 return ''
2485
2486
2487def _CheckForInvalidOSMacrosInFile(input_api, f):
2488 """Check for sensible looking, totally invalid OS macros."""
2489 preprocessor_statement = input_api.re.compile(r'^\s*#')
2490 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2491 results = []
2492 for lnum, line in f.ChangedContents():
2493 if preprocessor_statement.search(line):
2494 for match in os_macro.finditer(line):
2495 if not match.group(1) in _VALID_OS_MACROS:
2496 good = _DidYouMeanOSMacro(match.group(1))
2497 did_you_mean = ' (did you mean %s?)' % good if good else ''
2498 results.append(' %s:%d %s%s' % (f.LocalPath(),
2499 lnum,
2500 match.group(1),
2501 did_you_mean))
2502 return results
2503
2504
2505def _CheckForInvalidOSMacros(input_api, output_api):
2506 """Check all affected files for invalid OS macros."""
2507 bad_macros = []
2508 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472509 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542510 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2511
2512 if not bad_macros:
2513 return []
2514
2515 return [output_api.PresubmitError(
2516 'Possibly invalid OS macro[s] found. Please fix your code\n'
2517 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2518
lliabraa35bab3932014-10-01 12:16:442519
2520def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2521 """Check all affected files for invalid "if defined" macros."""
2522 ALWAYS_DEFINED_MACROS = (
2523 "TARGET_CPU_PPC",
2524 "TARGET_CPU_PPC64",
2525 "TARGET_CPU_68K",
2526 "TARGET_CPU_X86",
2527 "TARGET_CPU_ARM",
2528 "TARGET_CPU_MIPS",
2529 "TARGET_CPU_SPARC",
2530 "TARGET_CPU_ALPHA",
2531 "TARGET_IPHONE_SIMULATOR",
2532 "TARGET_OS_EMBEDDED",
2533 "TARGET_OS_IPHONE",
2534 "TARGET_OS_MAC",
2535 "TARGET_OS_UNIX",
2536 "TARGET_OS_WIN32",
2537 )
2538 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2539 results = []
2540 for lnum, line in f.ChangedContents():
2541 for match in ifdef_macro.finditer(line):
2542 if match.group(1) in ALWAYS_DEFINED_MACROS:
2543 always_defined = ' %s is always defined. ' % match.group(1)
2544 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2545 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2546 lnum,
2547 always_defined,
2548 did_you_mean))
2549 return results
2550
2551
2552def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2553 """Check all affected files for invalid "if defined" macros."""
2554 bad_macros = []
2555 for f in input_api.AffectedFiles():
sdefresne4e1eccb32017-05-24 08:45:212556 if f.LocalPath().startswith('third_party/sqlite/'):
2557 continue
lliabraa35bab3932014-10-01 12:16:442558 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2559 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2560
2561 if not bad_macros:
2562 return []
2563
2564 return [output_api.PresubmitError(
2565 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2566 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2567 bad_macros)]
2568
2569
mlamouria82272622014-09-16 18:45:042570def _CheckForIPCRules(input_api, output_api):
2571 """Check for same IPC rules described in
2572 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2573 """
2574 base_pattern = r'IPC_ENUM_TRAITS\('
2575 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2576 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2577
2578 problems = []
2579 for f in input_api.AffectedSourceFiles(None):
2580 local_path = f.LocalPath()
2581 if not local_path.endswith('.h'):
2582 continue
2583 for line_number, line in f.ChangedContents():
2584 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2585 problems.append(
2586 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2587
2588 if problems:
2589 return [output_api.PresubmitPromptWarning(
2590 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2591 else:
2592 return []
2593
[email protected]b00342e7f2013-03-26 16:21:542594
mostynbb639aca52015-01-07 20:31:232595def _CheckForWindowsLineEndings(input_api, output_api):
2596 """Check source code and known ascii text files for Windows style line
2597 endings.
2598 """
earthdok1b5e0ee2015-03-10 15:19:102599 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232600
2601 file_inclusion_pattern = (
2602 known_text_files,
2603 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2604 )
2605
2606 filter = lambda f: input_api.FilterSourceFile(
2607 f, white_list=file_inclusion_pattern, black_list=None)
2608 files = [f.LocalPath() for f in
2609 input_api.AffectedSourceFiles(filter)]
2610
2611 problems = []
2612
2613 for file in files:
2614 fp = open(file, 'r')
2615 for line in fp:
2616 if line.endswith('\r\n'):
2617 problems.append(file)
2618 break
2619 fp.close()
2620
2621 if problems:
2622 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2623 'these files to contain Windows style line endings?\n' +
2624 '\n'.join(problems))]
2625
2626 return []
2627
2628
pastarmovj89f7ee12016-09-20 14:58:132629def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2630 lint_filters=None, verbose_level=None):
2631 """Checks that all source files use SYSLOG properly."""
2632 syslog_files = []
2633 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562634 for line_number, line in f.ChangedContents():
2635 if 'SYSLOG' in line:
2636 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2637
pastarmovj89f7ee12016-09-20 14:58:132638 if syslog_files:
2639 return [output_api.PresubmitPromptWarning(
2640 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2641 ' calls.\nFiles to check:\n', items=syslog_files)]
2642 return []
2643
2644
[email protected]1f7b4172010-01-28 01:17:342645def CheckChangeOnUpload(input_api, output_api):
2646 results = []
2647 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472648 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282649 results.extend(
jam93a6ee792017-02-08 23:59:222650 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192651 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222652 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132653 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162654 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542655 return results
[email protected]ca8d19842009-02-19 16:33:122656
2657
[email protected]1bfb8322014-04-23 01:02:412658def GetTryServerMasterForBot(bot):
2659 """Returns the Try Server master for the given bot.
2660
[email protected]0bb112362014-07-26 04:38:322661 It tries to guess the master from the bot name, but may still fail
2662 and return None. There is no longer a default master.
2663 """
2664 # Potentially ambiguous bot names are listed explicitly.
2665 master_map = {
tandriie5587792016-07-14 00:34:502666 'chromium_presubmit': 'master.tryserver.chromium.linux',
2667 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412668 }
[email protected]0bb112362014-07-26 04:38:322669 master = master_map.get(bot)
2670 if not master:
wnwen4fbaab82016-05-25 12:54:362671 if 'android' in bot:
tandriie5587792016-07-14 00:34:502672 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362673 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502674 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322675 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502676 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322677 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502678 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322679 return master
[email protected]1bfb8322014-04-23 01:02:412680
2681
[email protected]ca8d19842009-02-19 16:33:122682def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542683 results = []
[email protected]1f7b4172010-01-28 01:17:342684 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542685 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272686 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342687 input_api,
2688 output_api,
[email protected]2fdd1f362013-01-16 03:56:032689 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272690
jam93a6ee792017-02-08 23:59:222691 results.extend(
2692 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542693 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2694 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412695 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2696 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542697 return results