blob: 1a3c40cad2c6ce5a6da975439b09b8593e3f1ae6 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
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",
[email protected]4306417642009-06-11 00:33:4026)
[email protected]ca8d1982009-02-19 16:33:1227
wnwenbdc444e2016-05-25 13:44:1528
jochen9ea8fdbc2014-09-25 13:21:3529# The NetscapePlugIn library is excluded from pan-project as it will soon
30# be deleted together with the rest of the NPAPI and it's not worthwhile to
31# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3832_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3233 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3834)
35
wnwenbdc444e2016-05-25 13:44:1536
[email protected]06e6d0ff2012-12-11 01:36:4437# Fragment of a regular expression that matches C++ and Objective-C++
38# implementation files.
39_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
40
wnwenbdc444e2016-05-25 13:44:1541
[email protected]06e6d0ff2012-12-11 01:36:4442# Regular expression that matches code only used for test binaries
43# (best effort).
44_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4945 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4446 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3247 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1248 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4449 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4950 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0551 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4952 r'content[\\\/]shell[\\\/].*',
[email protected]06e6d0ff2012-12-11 01:36:4453 # At request of folks maintaining this folder.
joaodasilva718f87672014-08-30 09:25:4954 r'chrome[\\\/]browser[\\\/]automation[\\\/].*',
[email protected]7b054982013-11-27 00:44:4755 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4956 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0857 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4958 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4459)
[email protected]ca8d1982009-02-19 16:33:1260
wnwenbdc444e2016-05-25 13:44:1561
[email protected]eea609a2011-11-18 13:10:1262_TEST_ONLY_WARNING = (
63 'You might be calling functions intended only for testing from\n'
64 'production code. It is OK to ignore this warning if you know what\n'
65 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5866 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1267
68
[email protected]cf9b78f2012-11-14 11:40:2869_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4070 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2171 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
72 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2873
wnwenbdc444e2016-05-25 13:44:1574
[email protected]127f18ec2012-06-16 05:05:5975_BANNED_OBJC_FUNCTIONS = (
76 (
77 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2078 (
79 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5980 'prohibited. Please use CrTrackingArea instead.',
81 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
82 ),
83 False,
84 ),
85 (
[email protected]eaae1972014-04-16 04:17:2686 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2087 (
88 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5989 'instead.',
90 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
91 ),
92 False,
93 ),
94 (
95 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2096 (
97 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5998 'Please use |convertPoint:(point) fromView:nil| instead.',
99 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
100 ),
101 True,
102 ),
103 (
104 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20105 (
106 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59107 'Please use |convertPoint:(point) toView:nil| instead.',
108 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
109 ),
110 True,
111 ),
112 (
113 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20114 (
115 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59116 'Please use |convertRect:(point) fromView:nil| instead.',
117 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
118 ),
119 True,
120 ),
121 (
122 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20123 (
124 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59125 'Please use |convertRect:(point) toView:nil| instead.',
126 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
127 ),
128 True,
129 ),
130 (
131 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20132 (
133 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59134 'Please use |convertSize:(point) fromView:nil| instead.',
135 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
136 ),
137 True,
138 ),
139 (
140 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20141 (
142 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59143 'Please use |convertSize:(point) toView:nil| instead.',
144 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
145 ),
146 True,
147 ),
148)
149
150
151_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20152 # Make sure that gtest's FRIEND_TEST() macro is not used; the
153 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30154 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20155 (
156 'FRIEND_TEST(',
157 (
[email protected]e3c945502012-06-26 20:01:49158 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20159 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
160 ),
161 False,
[email protected]7345da02012-11-27 14:31:49162 (),
[email protected]23e6cbc2012-06-16 18:51:20163 ),
164 (
165 'ScopedAllowIO',
166 (
[email protected]e3c945502012-06-26 20:01:49167 'New code should not use ScopedAllowIO. Post a task to the blocking',
168 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20169 ),
[email protected]e3c945502012-06-26 20:01:49170 True,
[email protected]7345da02012-11-27 14:31:49171 (
nyad2c548b2015-12-09 03:22:32172 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10173 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49174 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22175 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31176 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51177 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
178 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09179 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49180 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
181 r"test_info_extractor\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41182 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
183 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
jamesra03ae492014-10-03 04:26:48184 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
185 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01186 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
[email protected]1f52a572014-05-12 23:21:54187 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
joedow91151042016-02-08 21:18:13188 r"^remoting[\\\/]host[\\\/]security_key[\\\/]"
189 "gnubby_auth_handler_linux\.cc$",
kylechar507532e62016-06-27 19:47:19190 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
191 "drm_display_host_manager\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53192 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
193 "material_design_controller\.cc$",
[email protected]7345da02012-11-27 14:31:49194 ),
[email protected]23e6cbc2012-06-16 18:51:20195 ),
[email protected]52657f62013-05-20 05:30:31196 (
tomhudsone2c14d552016-05-26 17:07:46197 'setMatrixClip',
198 (
199 'Overriding setMatrixClip() is prohibited; ',
200 'the base function is deprecated. ',
201 ),
202 True,
203 (),
204 ),
205 (
[email protected]52657f62013-05-20 05:30:31206 'SkRefPtr',
207 (
208 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22209 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31210 ),
211 True,
212 (),
213 ),
214 (
215 'SkAutoRef',
216 (
217 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22218 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31219 ),
220 True,
221 (),
222 ),
223 (
224 'SkAutoTUnref',
225 (
226 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22227 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31228 ),
229 True,
230 (),
231 ),
232 (
233 'SkAutoUnref',
234 (
235 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
236 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22237 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31238 ),
239 True,
240 (),
241 ),
[email protected]d89eec82013-12-03 14:10:59242 (
243 r'/HANDLE_EINTR\(.*close',
244 (
245 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
246 'descriptor will be closed, and it is incorrect to retry the close.',
247 'Either call close directly and ignore its return value, or wrap close',
248 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
249 ),
250 True,
251 (),
252 ),
253 (
254 r'/IGNORE_EINTR\((?!.*close)',
255 (
256 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
257 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
258 ),
259 True,
260 (
261 # Files that #define IGNORE_EINTR.
262 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
263 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
264 ),
265 ),
[email protected]ec5b3f02014-04-04 18:43:43266 (
267 r'/v8::Extension\(',
268 (
269 'Do not introduce new v8::Extensions into the code base, use',
270 'gin::Wrappable instead. See http://crbug.com/334679',
271 ),
272 True,
[email protected]f55c90ee62014-04-12 00:50:03273 (
joaodasilva718f87672014-08-30 09:25:49274 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03275 ),
[email protected]ec5b3f02014-04-04 18:43:43276 ),
skyostilf9469f72015-04-20 10:38:52277 (
sdefresneeaeccc52015-04-22 08:18:32278 '\<MessageLoopProxy\>',
skyostilf9469f72015-04-20 10:38:52279 (
280 'MessageLoopProxy is deprecated. ',
281 'Please use SingleThreadTaskRunner or ThreadTaskRunnerHandle instead.'
282 ),
283 True,
kinuko59024ce2015-04-21 22:18:30284 (
285 # Internal message_loop related code may still use it.
286 r'^base[\\\/]message_loop[\\\/].*',
287 ),
skyostilf9469f72015-04-20 10:38:52288 ),
jame2d1a952016-04-02 00:27:10289 (
290 '#pragma comment(lib,',
291 (
292 'Specify libraries to link with in build files and not in the source.',
293 ),
294 True,
295 (),
296 ),
[email protected]127f18ec2012-06-16 05:05:59297)
298
wnwenbdc444e2016-05-25 13:44:15299
mlamouria82272622014-09-16 18:45:04300_IPC_ENUM_TRAITS_DEPRECATED = (
301 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
302 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
303
[email protected]127f18ec2012-06-16 05:05:59304
[email protected]b00342e7f2013-03-26 16:21:54305_VALID_OS_MACROS = (
306 # Please keep sorted.
307 'OS_ANDROID',
308 'OS_BSD',
309 'OS_CAT', # For testing.
310 'OS_CHROMEOS',
311 'OS_FREEBSD',
312 'OS_IOS',
313 'OS_LINUX',
314 'OS_MACOSX',
315 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21316 'OS_NACL_NONSFI',
317 'OS_NACL_SFI',
[email protected]b00342e7f2013-03-26 16:21:54318 'OS_OPENBSD',
319 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37320 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54321 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54322 'OS_WIN',
323)
324
325
agrievef32bcc72016-04-04 14:57:40326_ANDROID_SPECIFIC_PYDEPS_FILES = [
327 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19328 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40329]
330
wnwenbdc444e2016-05-25 13:44:15331
agrievef32bcc72016-04-04 14:57:40332_GENERIC_PYDEPS_FILES = [
333 'build/secondary/tools/swarming_client/isolate.pydeps',
334]
335
wnwenbdc444e2016-05-25 13:44:15336
agrievef32bcc72016-04-04 14:57:40337_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
338
339
[email protected]55459852011-08-10 15:17:19340def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
341 """Attempts to prevent use of functions intended only for testing in
342 non-testing code. For now this is just a best-effort implementation
343 that ignores header files and may have some false positives. A
344 better implementation would probably need a proper C++ parser.
345 """
346 # We only scan .cc files and the like, as the declaration of
347 # for-testing functions in header files are hard to distinguish from
348 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44349 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19350
jochenc0d4808c2015-07-27 09:25:42351 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19352 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09353 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19354 exclusion_pattern = input_api.re.compile(
355 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
356 base_function_pattern, base_function_pattern))
357
358 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44359 black_list = (_EXCLUDED_PATHS +
360 _TEST_CODE_EXCLUDED_PATHS +
361 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19362 return input_api.FilterSourceFile(
363 affected_file,
364 white_list=(file_inclusion_pattern, ),
365 black_list=black_list)
366
367 problems = []
368 for f in input_api.AffectedSourceFiles(FilterFile):
369 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24370 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03371 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46372 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03373 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19374 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03375 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19376
377 if problems:
[email protected]f7051d52013-04-02 18:31:42378 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03379 else:
380 return []
[email protected]55459852011-08-10 15:17:19381
382
[email protected]10689ca2011-09-02 02:31:54383def _CheckNoIOStreamInHeaders(input_api, output_api):
384 """Checks to make sure no .h files include <iostream>."""
385 files = []
386 pattern = input_api.re.compile(r'^#include\s*<iostream>',
387 input_api.re.MULTILINE)
388 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
389 if not f.LocalPath().endswith('.h'):
390 continue
391 contents = input_api.ReadFile(f)
392 if pattern.search(contents):
393 files.append(f)
394
395 if len(files):
yolandyandaabc6d2016-04-18 18:29:39396 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06397 'Do not #include <iostream> in header files, since it inserts static '
398 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54399 '#include <ostream>. See http://crbug.com/94794',
400 files) ]
401 return []
402
403
[email protected]72df4e782012-06-21 16:28:18404def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52405 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18406 problems = []
407 for f in input_api.AffectedFiles():
408 if (not f.LocalPath().endswith(('.cc', '.mm'))):
409 continue
410
411 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04412 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18413 problems.append(' %s:%d' % (f.LocalPath(), line_num))
414
415 if not problems:
416 return []
417 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
418 '\n'.join(problems))]
419
420
danakj61c1aa22015-10-26 19:55:52421def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
422 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
423 errors = []
424 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
425 input_api.re.MULTILINE)
426 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
427 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
428 continue
429 for lnum, line in f.ChangedContents():
430 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17431 errors.append(output_api.PresubmitError(
432 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
433 'DCHECK_IS_ON()", not forgetting the braces.')
434 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52435 return errors
436
437
mcasasb7440c282015-02-04 14:52:19438def _FindHistogramNameInLine(histogram_name, line):
439 """Tries to find a histogram name or prefix in a line."""
440 if not "affected-histogram" in line:
441 return histogram_name in line
442 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
443 # the histogram_name.
444 if not '"' in line:
445 return False
446 histogram_prefix = line.split('\"')[1]
447 return histogram_prefix in histogram_name
448
449
450def _CheckUmaHistogramChanges(input_api, output_api):
451 """Check that UMA histogram names in touched lines can still be found in other
452 lines of the patch or in histograms.xml. Note that this check would not catch
453 the reverse: changes in histograms.xml not matched in the code itself."""
454 touched_histograms = []
455 histograms_xml_modifications = []
456 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
457 for f in input_api.AffectedFiles():
458 # If histograms.xml itself is modified, keep the modified lines for later.
459 if f.LocalPath().endswith(('histograms.xml')):
460 histograms_xml_modifications = f.ChangedContents()
461 continue
462 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
463 continue
464 for line_num, line in f.ChangedContents():
465 found = pattern.search(line)
466 if found:
467 touched_histograms.append([found.group(1), f, line_num])
468
469 # Search for the touched histogram names in the local modifications to
470 # histograms.xml, and, if not found, on the base histograms.xml file.
471 unmatched_histograms = []
472 for histogram_info in touched_histograms:
473 histogram_name_found = False
474 for line_num, line in histograms_xml_modifications:
475 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
476 if histogram_name_found:
477 break
478 if not histogram_name_found:
479 unmatched_histograms.append(histogram_info)
480
eromanb90c82e7e32015-04-01 15:13:49481 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19482 problems = []
483 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49484 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19485 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45486 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19487 histogram_name_found = False
488 for line in histograms_xml:
489 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
490 if histogram_name_found:
491 break
492 if not histogram_name_found:
493 problems.append(' [%s:%d] %s' %
494 (f.LocalPath(), line_num, histogram_name))
495
496 if not problems:
497 return []
498 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
499 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49500 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19501
wnwenbdc444e2016-05-25 13:44:15502
yolandyandaabc6d2016-04-18 18:29:39503def _CheckFlakyTestUsage(input_api, output_api):
504 """Check that FlakyTest annotation is our own instead of the android one"""
505 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
506 files = []
507 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
508 if f.LocalPath().endswith('Test.java'):
509 if pattern.search(input_api.ReadFile(f)):
510 files.append(f)
511 if len(files):
512 return [output_api.PresubmitError(
513 'Use org.chromium.base.test.util.FlakyTest instead of '
514 'android.test.FlakyTest',
515 files)]
516 return []
mcasasb7440c282015-02-04 14:52:19517
wnwenbdc444e2016-05-25 13:44:15518
[email protected]8ea5d4b2011-09-13 21:49:22519def _CheckNoNewWStrings(input_api, output_api):
520 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27521 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22522 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20523 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57524 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
525 '/win/' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20526 continue
[email protected]8ea5d4b2011-09-13 21:49:22527
[email protected]a11dbe9b2012-08-07 01:32:58528 allowWString = False
[email protected]b5c24292011-11-28 14:38:20529 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58530 if 'presubmit: allow wstring' in line:
531 allowWString = True
532 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27533 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58534 allowWString = False
535 else:
536 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22537
[email protected]55463aa62011-10-12 00:48:27538 if not problems:
539 return []
540 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58541 ' If you are calling a cross-platform API that accepts a wstring, '
542 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27543 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22544
545
[email protected]2a8ac9c2011-10-19 17:20:44546def _CheckNoDEPSGIT(input_api, output_api):
547 """Make sure .DEPS.git is never modified manually."""
548 if any(f.LocalPath().endswith('.DEPS.git') for f in
549 input_api.AffectedFiles()):
550 return [output_api.PresubmitError(
551 'Never commit changes to .DEPS.git. This file is maintained by an\n'
552 'automated system based on what\'s in DEPS and your changes will be\n'
553 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34554 '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:44555 'for more information')]
556 return []
557
558
tandriief664692014-09-23 14:51:47559def _CheckValidHostsInDEPS(input_api, output_api):
560 """Checks that DEPS file deps are from allowed_hosts."""
561 # Run only if DEPS file has been modified to annoy fewer bystanders.
562 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
563 return []
564 # Outsource work to gclient verify
565 try:
566 input_api.subprocess.check_output(['gclient', 'verify'])
567 return []
568 except input_api.subprocess.CalledProcessError, error:
569 return [output_api.PresubmitError(
570 'DEPS file must have only git dependencies.',
571 long_text=error.output)]
572
573
[email protected]127f18ec2012-06-16 05:05:59574def _CheckNoBannedFunctions(input_api, output_api):
575 """Make sure that banned functions are not used."""
576 warnings = []
577 errors = []
578
wnwenbdc444e2016-05-25 13:44:15579 def IsBlacklisted(affected_file, blacklist):
580 local_path = affected_file.LocalPath()
581 for item in blacklist:
582 if input_api.re.match(item, local_path):
583 return True
584 return False
585
586 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
587 matched = False
588 if func_name[0:1] == '/':
589 regex = func_name[1:]
590 if input_api.re.search(regex, line):
591 matched = True
592 elif func_name in line:
dchenge07de812016-06-20 19:27:17593 matched = True
wnwenbdc444e2016-05-25 13:44:15594 if matched:
dchenge07de812016-06-20 19:27:17595 problems = warnings
wnwenbdc444e2016-05-25 13:44:15596 if error:
dchenge07de812016-06-20 19:27:17597 problems = errors
wnwenbdc444e2016-05-25 13:44:15598 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
599 for message_line in message:
600 problems.append(' %s' % message_line)
601
[email protected]127f18ec2012-06-16 05:05:59602 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
603 for f in input_api.AffectedFiles(file_filter=file_filter):
604 for line_num, line in f.ChangedContents():
605 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15606 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59607
608 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
609 for f in input_api.AffectedFiles(file_filter=file_filter):
610 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49611 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49612 if IsBlacklisted(f, excluded_paths):
613 continue
wnwenbdc444e2016-05-25 13:44:15614 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59615
616 result = []
617 if (warnings):
618 result.append(output_api.PresubmitPromptWarning(
619 'Banned functions were used.\n' + '\n'.join(warnings)))
620 if (errors):
621 result.append(output_api.PresubmitError(
622 'Banned functions were used.\n' + '\n'.join(errors)))
623 return result
624
625
[email protected]6c063c62012-07-11 19:11:06626def _CheckNoPragmaOnce(input_api, output_api):
627 """Make sure that banned functions are not used."""
628 files = []
629 pattern = input_api.re.compile(r'^#pragma\s+once',
630 input_api.re.MULTILINE)
631 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
632 if not f.LocalPath().endswith('.h'):
633 continue
634 contents = input_api.ReadFile(f)
635 if pattern.search(contents):
636 files.append(f)
637
638 if files:
639 return [output_api.PresubmitError(
640 'Do not use #pragma once in header files.\n'
641 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
642 files)]
643 return []
644
[email protected]127f18ec2012-06-16 05:05:59645
[email protected]e7479052012-09-19 00:26:12646def _CheckNoTrinaryTrueFalse(input_api, output_api):
647 """Checks to make sure we don't introduce use of foo ? true : false."""
648 problems = []
649 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
650 for f in input_api.AffectedFiles():
651 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
652 continue
653
654 for line_num, line in f.ChangedContents():
655 if pattern.match(line):
656 problems.append(' %s:%d' % (f.LocalPath(), line_num))
657
658 if not problems:
659 return []
660 return [output_api.PresubmitPromptWarning(
661 'Please consider avoiding the "? true : false" pattern if possible.\n' +
662 '\n'.join(problems))]
663
664
[email protected]55f9f382012-07-31 11:02:18665def _CheckUnwantedDependencies(input_api, output_api):
666 """Runs checkdeps on #include statements added in this
667 change. Breaking - rules is an error, breaking ! rules is a
668 warning.
669 """
mohan.reddyf21db962014-10-16 12:26:47670 import sys
[email protected]55f9f382012-07-31 11:02:18671 # We need to wait until we have an input_api object and use this
672 # roundabout construct to import checkdeps because this file is
673 # eval-ed and thus doesn't have __file__.
674 original_sys_path = sys.path
675 try:
676 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47677 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18678 import checkdeps
679 from cpp_checker import CppChecker
680 from rules import Rule
681 finally:
682 # Restore sys.path to what it was before.
683 sys.path = original_sys_path
684
685 added_includes = []
686 for f in input_api.AffectedFiles():
687 if not CppChecker.IsCppFile(f.LocalPath()):
688 continue
689
690 changed_lines = [line for line_num, line in f.ChangedContents()]
691 added_includes.append([f.LocalPath(), changed_lines])
692
[email protected]26385172013-05-09 23:11:35693 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18694
695 error_descriptions = []
696 warning_descriptions = []
697 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
698 added_includes):
699 description_with_path = '%s\n %s' % (path, rule_description)
700 if rule_type == Rule.DISALLOW:
701 error_descriptions.append(description_with_path)
702 else:
703 warning_descriptions.append(description_with_path)
704
705 results = []
706 if error_descriptions:
707 results.append(output_api.PresubmitError(
708 'You added one or more #includes that violate checkdeps rules.',
709 error_descriptions))
710 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42711 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18712 'You added one or more #includes of files that are temporarily\n'
713 'allowed but being removed. Can you avoid introducing the\n'
714 '#include? See relevant DEPS file(s) for details and contacts.',
715 warning_descriptions))
716 return results
717
718
[email protected]fbcafe5a2012-08-08 15:31:22719def _CheckFilePermissions(input_api, output_api):
720 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15721 if input_api.platform == 'win32':
722 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29723 checkperms_tool = input_api.os_path.join(
724 input_api.PresubmitLocalPath(),
725 'tools', 'checkperms', 'checkperms.py')
726 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47727 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22728 for f in input_api.AffectedFiles():
729 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11730 try:
731 input_api.subprocess.check_output(args)
732 return []
733 except input_api.subprocess.CalledProcessError as error:
734 return [output_api.PresubmitError(
735 'checkperms.py failed:',
736 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22737
738
[email protected]c8278b32012-10-30 20:35:49739def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
740 """Makes sure we don't include ui/aura/window_property.h
741 in header files.
742 """
743 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
744 errors = []
745 for f in input_api.AffectedFiles():
746 if not f.LocalPath().endswith('.h'):
747 continue
748 for line_num, line in f.ChangedContents():
749 if pattern.match(line):
750 errors.append(' %s:%d' % (f.LocalPath(), line_num))
751
752 results = []
753 if errors:
754 results.append(output_api.PresubmitError(
755 'Header files should not include ui/aura/window_property.h', errors))
756 return results
757
758
[email protected]cf9b78f2012-11-14 11:40:28759def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
760 """Checks that the lines in scope occur in the right order.
761
762 1. C system files in alphabetical order
763 2. C++ system files in alphabetical order
764 3. Project's .h files
765 """
766
767 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
768 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
769 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
770
771 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
772
773 state = C_SYSTEM_INCLUDES
774
775 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57776 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28777 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55778 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28779 for line_num, line in scope:
780 if c_system_include_pattern.match(line):
781 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55782 problem_linenums.append((line_num, previous_line_num,
783 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28784 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55785 problem_linenums.append((line_num, previous_line_num,
786 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28787 elif cpp_system_include_pattern.match(line):
788 if state == C_SYSTEM_INCLUDES:
789 state = CPP_SYSTEM_INCLUDES
790 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55791 problem_linenums.append((line_num, previous_line_num,
792 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28793 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55794 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28795 elif custom_include_pattern.match(line):
796 if state != CUSTOM_INCLUDES:
797 state = CUSTOM_INCLUDES
798 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55799 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28800 else:
brucedawson70fadb02015-06-30 17:47:55801 problem_linenums.append((line_num, previous_line_num,
802 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28803 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57804 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28805
806 warnings = []
brucedawson70fadb02015-06-30 17:47:55807 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57808 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55809 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28810 return warnings
811
812
[email protected]ac294a12012-12-06 16:38:43813def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28814 """Checks the #include order for the given file f."""
815
[email protected]2299dcf2012-11-15 19:56:24816 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30817 # Exclude the following includes from the check:
818 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
819 # specific order.
820 # 2) <atlbase.h>, "build/build_config.h"
821 excluded_include_pattern = input_api.re.compile(
822 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24823 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33824 # Match the final or penultimate token if it is xxxtest so we can ignore it
825 # when considering the special first include.
826 test_file_tag_pattern = input_api.re.compile(
827 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11828 if_pattern = input_api.re.compile(
829 r'\s*#\s*(if|elif|else|endif|define|undef).*')
830 # Some files need specialized order of includes; exclude such files from this
831 # check.
832 uncheckable_includes_pattern = input_api.re.compile(
833 r'\s*#include '
834 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28835
836 contents = f.NewContents()
837 warnings = []
838 line_num = 0
839
[email protected]ac294a12012-12-06 16:38:43840 # Handle the special first include. If the first include file is
841 # some/path/file.h, the corresponding including file can be some/path/file.cc,
842 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
843 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33844 # If the included file is some/path/file_platform.h the including file could
845 # also be some/path/file_xxxtest_platform.h.
846 including_file_base_name = test_file_tag_pattern.sub(
847 '', input_api.os_path.basename(f.LocalPath()))
848
[email protected]ac294a12012-12-06 16:38:43849 for line in contents:
850 line_num += 1
851 if system_include_pattern.match(line):
852 # No special first include -> process the line again along with normal
853 # includes.
854 line_num -= 1
855 break
856 match = custom_include_pattern.match(line)
857 if match:
858 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33859 header_basename = test_file_tag_pattern.sub(
860 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
861
862 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24863 # No special first include -> process the line again along with normal
864 # includes.
865 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43866 break
[email protected]cf9b78f2012-11-14 11:40:28867
868 # Split into scopes: Each region between #if and #endif is its own scope.
869 scopes = []
870 current_scope = []
871 for line in contents[line_num:]:
872 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11873 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54874 continue
[email protected]2309b0fa02012-11-16 12:18:27875 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28876 scopes.append(current_scope)
877 current_scope = []
[email protected]962f117e2012-11-22 18:11:56878 elif ((system_include_pattern.match(line) or
879 custom_include_pattern.match(line)) and
880 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28881 current_scope.append((line_num, line))
882 scopes.append(current_scope)
883
884 for scope in scopes:
885 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
886 changed_linenums))
887 return warnings
888
889
890def _CheckIncludeOrder(input_api, output_api):
891 """Checks that the #include order is correct.
892
893 1. The corresponding header for source files.
894 2. C system files in alphabetical order
895 3. C++ system files in alphabetical order
896 4. Project's .h files in alphabetical order
897
[email protected]ac294a12012-12-06 16:38:43898 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
899 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28900 """
[email protected]e120b012014-08-15 19:08:35901 def FileFilterIncludeOrder(affected_file):
902 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
903 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28904
905 warnings = []
[email protected]e120b012014-08-15 19:08:35906 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08907 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43908 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
909 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28910
911 results = []
912 if warnings:
[email protected]f7051d52013-04-02 18:31:42913 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53914 warnings))
[email protected]cf9b78f2012-11-14 11:40:28915 return results
916
917
[email protected]70ca77752012-11-20 03:45:03918def _CheckForVersionControlConflictsInFile(input_api, f):
919 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
920 errors = []
921 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23922 if f.LocalPath().endswith('.md'):
923 # First-level headers in markdown look a lot like version control
924 # conflict markers. http://daringfireball.net/projects/markdown/basics
925 continue
[email protected]70ca77752012-11-20 03:45:03926 if pattern.match(line):
927 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
928 return errors
929
930
931def _CheckForVersionControlConflicts(input_api, output_api):
932 """Usually this is not intentional and will cause a compile failure."""
933 errors = []
934 for f in input_api.AffectedFiles():
935 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
936
937 results = []
938 if errors:
939 results.append(output_api.PresubmitError(
940 'Version control conflict markers found, please resolve.', errors))
941 return results
942
943
[email protected]06e6d0ff2012-12-11 01:36:44944def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
945 def FilterFile(affected_file):
946 """Filter function for use with input_api.AffectedSourceFiles,
947 below. This filters out everything except non-test files from
948 top-level directories that generally speaking should not hard-code
949 service URLs (e.g. src/android_webview/, src/content/ and others).
950 """
951 return input_api.FilterSourceFile(
952 affected_file,
[email protected]78bb39d62012-12-11 15:11:56953 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44954 black_list=(_EXCLUDED_PATHS +
955 _TEST_CODE_EXCLUDED_PATHS +
956 input_api.DEFAULT_BLACK_LIST))
957
reillyi38965732015-11-16 18:27:33958 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
959 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:46960 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
961 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:44962 problems = [] # items are (filename, line_number, line)
963 for f in input_api.AffectedSourceFiles(FilterFile):
964 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:46965 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:44966 problems.append((f.LocalPath(), line_num, line))
967
968 if problems:
[email protected]f7051d52013-04-02 18:31:42969 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44970 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:58971 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:44972 [' %s:%d: %s' % (
973 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03974 else:
975 return []
[email protected]06e6d0ff2012-12-11 01:36:44976
977
[email protected]d2530012013-01-25 16:39:27978def _CheckNoAbbreviationInPngFileName(input_api, output_api):
979 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:31980 The native_client_sdk directory is excluded because it has auto-generated PNG
981 files for documentation.
[email protected]d2530012013-01-25 16:39:27982 """
[email protected]d2530012013-01-25 16:39:27983 errors = []
binji0dcdf342014-12-12 18:32:31984 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
985 black_list = (r'^native_client_sdk[\\\/]',)
986 file_filter = lambda f: input_api.FilterSourceFile(
987 f, white_list=white_list, black_list=black_list)
988 for f in input_api.AffectedFiles(include_deletes=False,
989 file_filter=file_filter):
990 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:27991
992 results = []
993 if errors:
994 results.append(output_api.PresubmitError(
995 'The name of PNG files should not have abbreviations. \n'
996 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
997 'Contact [email protected] if you have questions.', errors))
998 return results
999
1000
[email protected]14a6131c2014-01-08 01:15:411001def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:081002 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411003 a set of DEPS entries that we should look up.
1004
1005 For a directory (rather than a specific filename) we fake a path to
1006 a specific filename by adding /DEPS. This is chosen as a file that
1007 will seldom or never be subject to per-file include_rules.
1008 """
[email protected]2b438d62013-11-14 17:54:141009 # We ignore deps entries on auto-generated directories.
1010 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081011
1012 # This pattern grabs the path without basename in the first
1013 # parentheses, and the basename (if present) in the second. It
1014 # relies on the simple heuristic that if there is a basename it will
1015 # be a header file ending in ".h".
1016 pattern = re.compile(
1017 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141018 results = set()
[email protected]f32e2d1e2013-07-26 21:39:081019 for changed_line in changed_lines:
1020 m = pattern.match(changed_line)
1021 if m:
1022 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:141023 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:411024 if m.group(2):
1025 results.add('%s%s' % (path, m.group(2)))
1026 else:
1027 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081028 return results
1029
1030
[email protected]e871964c2013-05-13 14:14:551031def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1032 """When a dependency prefixed with + is added to a DEPS file, we
1033 want to make sure that the change is reviewed by an OWNER of the
1034 target file or directory, to avoid layering violations from being
1035 introduced. This check verifies that this happens.
1036 """
1037 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241038
1039 file_filter = lambda f: not input_api.re.match(
1040 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1041 for f in input_api.AffectedFiles(include_deletes=False,
1042 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551043 filename = input_api.os_path.basename(f.LocalPath())
1044 if filename == 'DEPS':
1045 changed_lines |= set(line.strip()
1046 for line_num, line
1047 in f.ChangedContents())
1048 if not changed_lines:
1049 return []
1050
[email protected]14a6131c2014-01-08 01:15:411051 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1052 changed_lines)
[email protected]e871964c2013-05-13 14:14:551053 if not virtual_depended_on_files:
1054 return []
1055
1056 if input_api.is_committing:
1057 if input_api.tbr:
1058 return [output_api.PresubmitNotifyResult(
1059 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271060 if input_api.dry_run:
1061 return [output_api.PresubmitNotifyResult(
1062 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551063 if not input_api.change.issue:
1064 return [output_api.PresubmitError(
1065 "DEPS approval by OWNERS check failed: this change has "
1066 "no Rietveld issue number, so we can't check it for approvals.")]
1067 output = output_api.PresubmitError
1068 else:
1069 output = output_api.PresubmitNotifyResult
1070
1071 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501072 owner_email, reviewers = (
1073 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1074 input_api,
1075 owners_db.email_regexp,
1076 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551077
1078 owner_email = owner_email or input_api.change.author_email
1079
[email protected]de4f7d22013-05-23 14:27:461080 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511081 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461082 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551083 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1084 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411085
1086 # We strip the /DEPS part that was added by
1087 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1088 # directory.
1089 def StripDeps(path):
1090 start_deps = path.rfind('/DEPS')
1091 if start_deps != -1:
1092 return path[:start_deps]
1093 else:
1094 return path
1095 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551096 for path in missing_files]
1097
1098 if unapproved_dependencies:
1099 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151100 output('You need LGTM from owners of depends-on paths in DEPS that were '
1101 'modified in this CL:\n %s' %
1102 '\n '.join(sorted(unapproved_dependencies)))]
1103 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1104 output_list.append(output(
1105 'Suggested missing target path OWNERS:\n %s' %
1106 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551107 return output_list
1108
1109 return []
1110
1111
[email protected]85218562013-11-22 07:41:401112def _CheckSpamLogging(input_api, output_api):
1113 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1114 black_list = (_EXCLUDED_PATHS +
1115 _TEST_CODE_EXCLUDED_PATHS +
1116 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501117 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191118 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481119 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461120 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121121 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1122 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581123 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161124 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031125 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151126 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1127 r"^chromecast[\\\/]",
1128 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311129 r"^components[\\\/]html_viewer[\\\/]"
1130 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461131 # TODO(peter): Remove this exception. https://crbug.com/534537
1132 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1133 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251134 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1135 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241136 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111137 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151138 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111139 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521140 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501141 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361142 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311143 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131144 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441145 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451146 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021147 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441148 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401149 source_file_filter = lambda x: input_api.FilterSourceFile(
1150 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1151
1152 log_info = []
1153 printf = []
1154
1155 for f in input_api.AffectedSourceFiles(source_file_filter):
1156 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471157 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401158 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471159 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131160 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371161
mohan.reddyf21db962014-10-16 12:26:471162 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371163 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471164 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401165 printf.append(f.LocalPath())
1166
1167 if log_info:
1168 return [output_api.PresubmitError(
1169 'These files spam the console log with LOG(INFO):',
1170 items=log_info)]
1171 if printf:
1172 return [output_api.PresubmitError(
1173 'These files spam the console log with printf/fprintf:',
1174 items=printf)]
1175 return []
1176
1177
[email protected]49aa76a2013-12-04 06:59:161178def _CheckForAnonymousVariables(input_api, output_api):
1179 """These types are all expected to hold locks while in scope and
1180 so should never be anonymous (which causes them to be immediately
1181 destroyed)."""
1182 they_who_must_be_named = [
1183 'base::AutoLock',
1184 'base::AutoReset',
1185 'base::AutoUnlock',
1186 'SkAutoAlphaRestore',
1187 'SkAutoBitmapShaderInstall',
1188 'SkAutoBlitterChoose',
1189 'SkAutoBounderCommit',
1190 'SkAutoCallProc',
1191 'SkAutoCanvasRestore',
1192 'SkAutoCommentBlock',
1193 'SkAutoDescriptor',
1194 'SkAutoDisableDirectionCheck',
1195 'SkAutoDisableOvalCheck',
1196 'SkAutoFree',
1197 'SkAutoGlyphCache',
1198 'SkAutoHDC',
1199 'SkAutoLockColors',
1200 'SkAutoLockPixels',
1201 'SkAutoMalloc',
1202 'SkAutoMaskFreeImage',
1203 'SkAutoMutexAcquire',
1204 'SkAutoPathBoundsUpdate',
1205 'SkAutoPDFRelease',
1206 'SkAutoRasterClipValidate',
1207 'SkAutoRef',
1208 'SkAutoTime',
1209 'SkAutoTrace',
1210 'SkAutoUnref',
1211 ]
1212 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1213 # bad: base::AutoLock(lock.get());
1214 # not bad: base::AutoLock lock(lock.get());
1215 bad_pattern = input_api.re.compile(anonymous)
1216 # good: new base::AutoLock(lock.get())
1217 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1218 errors = []
1219
1220 for f in input_api.AffectedFiles():
1221 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1222 continue
1223 for linenum, line in f.ChangedContents():
1224 if bad_pattern.search(line) and not good_pattern.search(line):
1225 errors.append('%s:%d' % (f.LocalPath(), linenum))
1226
1227 if errors:
1228 return [output_api.PresubmitError(
1229 'These lines create anonymous variables that need to be named:',
1230 items=errors)]
1231 return []
1232
1233
[email protected]5fe0f8742013-11-29 01:04:591234def _CheckCygwinShell(input_api, output_api):
1235 source_file_filter = lambda x: input_api.FilterSourceFile(
1236 x, white_list=(r'.+\.(gyp|gypi)$',))
1237 cygwin_shell = []
1238
1239 for f in input_api.AffectedSourceFiles(source_file_filter):
1240 for linenum, line in f.ChangedContents():
1241 if 'msvs_cygwin_shell' in line:
1242 cygwin_shell.append(f.LocalPath())
1243 break
1244
1245 if cygwin_shell:
1246 return [output_api.PresubmitError(
1247 'These files should not use msvs_cygwin_shell (the default is 0):',
1248 items=cygwin_shell)]
1249 return []
1250
[email protected]85218562013-11-22 07:41:401251
[email protected]999261d2014-03-03 20:08:081252def _CheckUserActionUpdate(input_api, output_api):
1253 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521254 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081255 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521256 # If actions.xml is already included in the changelist, the PRESUBMIT
1257 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081258 return []
1259
[email protected]999261d2014-03-03 20:08:081260 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1261 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521262 current_actions = None
[email protected]999261d2014-03-03 20:08:081263 for f in input_api.AffectedFiles(file_filter=file_filter):
1264 for line_num, line in f.ChangedContents():
1265 match = input_api.re.search(action_re, line)
1266 if match:
[email protected]2f92dec2014-03-07 19:21:521267 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1268 # loaded only once.
1269 if not current_actions:
1270 with open('tools/metrics/actions/actions.xml') as actions_f:
1271 current_actions = actions_f.read()
1272 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081273 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521274 action = 'name="{0}"'.format(action_name)
1275 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081276 return [output_api.PresubmitPromptWarning(
1277 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521278 'tools/metrics/actions/actions.xml. Please run '
1279 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081280 % (f.LocalPath(), line_num, action_name))]
1281 return []
1282
1283
[email protected]99171a92014-06-03 08:44:471284def _GetJSONParseError(input_api, filename, eat_comments=True):
1285 try:
1286 contents = input_api.ReadFile(filename)
1287 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131288 import sys
1289 original_sys_path = sys.path
1290 try:
1291 sys.path = sys.path + [input_api.os_path.join(
1292 input_api.PresubmitLocalPath(),
1293 'tools', 'json_comment_eater')]
1294 import json_comment_eater
1295 finally:
1296 sys.path = original_sys_path
1297 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471298
1299 input_api.json.loads(contents)
1300 except ValueError as e:
1301 return e
1302 return None
1303
1304
1305def _GetIDLParseError(input_api, filename):
1306 try:
1307 contents = input_api.ReadFile(filename)
1308 idl_schema = input_api.os_path.join(
1309 input_api.PresubmitLocalPath(),
1310 'tools', 'json_schema_compiler', 'idl_schema.py')
1311 process = input_api.subprocess.Popen(
1312 [input_api.python_executable, idl_schema],
1313 stdin=input_api.subprocess.PIPE,
1314 stdout=input_api.subprocess.PIPE,
1315 stderr=input_api.subprocess.PIPE,
1316 universal_newlines=True)
1317 (_, error) = process.communicate(input=contents)
1318 return error or None
1319 except ValueError as e:
1320 return e
1321
1322
1323def _CheckParseErrors(input_api, output_api):
1324 """Check that IDL and JSON files do not contain syntax errors."""
1325 actions = {
1326 '.idl': _GetIDLParseError,
1327 '.json': _GetJSONParseError,
1328 }
1329 # These paths contain test data and other known invalid JSON files.
1330 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491331 r'test[\\\/]data[\\\/]',
1332 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471333 ]
1334 # Most JSON files are preprocessed and support comments, but these do not.
1335 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491336 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471337 ]
1338 # Only run IDL checker on files in these directories.
1339 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491340 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1341 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471342 ]
1343
1344 def get_action(affected_file):
1345 filename = affected_file.LocalPath()
1346 return actions.get(input_api.os_path.splitext(filename)[1])
1347
1348 def MatchesFile(patterns, path):
1349 for pattern in patterns:
1350 if input_api.re.search(pattern, path):
1351 return True
1352 return False
1353
1354 def FilterFile(affected_file):
1355 action = get_action(affected_file)
1356 if not action:
1357 return False
1358 path = affected_file.LocalPath()
1359
1360 if MatchesFile(excluded_patterns, path):
1361 return False
1362
1363 if (action == _GetIDLParseError and
1364 not MatchesFile(idl_included_patterns, path)):
1365 return False
1366 return True
1367
1368 results = []
1369 for affected_file in input_api.AffectedFiles(
1370 file_filter=FilterFile, include_deletes=False):
1371 action = get_action(affected_file)
1372 kwargs = {}
1373 if (action == _GetJSONParseError and
1374 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1375 kwargs['eat_comments'] = False
1376 parse_error = action(input_api,
1377 affected_file.AbsoluteLocalPath(),
1378 **kwargs)
1379 if parse_error:
1380 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1381 (affected_file.LocalPath(), parse_error)))
1382 return results
1383
1384
[email protected]760deea2013-12-10 19:33:491385def _CheckJavaStyle(input_api, output_api):
1386 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471387 import sys
[email protected]760deea2013-12-10 19:33:491388 original_sys_path = sys.path
1389 try:
1390 sys.path = sys.path + [input_api.os_path.join(
1391 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1392 import checkstyle
1393 finally:
1394 # Restore sys.path to what it was before.
1395 sys.path = original_sys_path
1396
1397 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091398 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511399 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491400
1401
dchenge07de812016-06-20 19:27:171402def _CheckIpcOwners(input_api, output_api):
1403 """Checks that affected files involving IPC have an IPC OWNERS rule.
1404
1405 Whether or not a file affects IPC is determined by a simple whitelist of
1406 filename patterns."""
1407 file_patterns = [
1408 '*_messages.cc',
1409 '*_messages*.h',
1410 '*_param_traits*.*',
1411 '*.mojom',
1412 '*_struct_traits*.*',
1413 '*_type_converter*.*',
1414 # Blink uses a different file naming convention
1415 '*StructTraits*.*',
1416 '*TypeConverter*.*',
1417 ]
1418
1419 # Dictionary mapping an OWNERS file path to Patterns.
1420 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1421 # rules ) to a PatternEntry.
1422 # PatternEntry is a dictionary with two keys:
1423 # - 'files': the files that are matched by this pattern
1424 # - 'rules': the per-file rules needed for this pattern
1425 # For example, if we expect OWNERS file to contain rules for *.mojom and
1426 # *_struct_traits*.*, Patterns might look like this:
1427 # {
1428 # '*.mojom': {
1429 # 'files': ...,
1430 # 'rules': [
1431 # 'per-file *.mojom=set noparent',
1432 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1433 # ],
1434 # },
1435 # '*_struct_traits*.*': {
1436 # 'files': ...,
1437 # 'rules': [
1438 # 'per-file *_struct_traits*.*=set noparent',
1439 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1440 # ],
1441 # },
1442 # }
1443 to_check = {}
1444
1445 # Iterate through the affected files to see what we actually need to check
1446 # for. We should only nag patch authors about per-file rules if a file in that
1447 # directory would match that pattern. If a directory only contains *.mojom
1448 # files and no *_messages*.h files, we should only nag about rules for
1449 # *.mojom files.
rockot51249332016-06-23 16:32:251450 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171451 for pattern in file_patterns:
1452 if input_api.fnmatch.fnmatch(
1453 input_api.os_path.basename(f.LocalPath()), pattern):
1454 owners_file = input_api.os_path.join(
1455 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1456 if owners_file not in to_check:
1457 to_check[owners_file] = {}
1458 if pattern not in to_check[owners_file]:
1459 to_check[owners_file][pattern] = {
1460 'files': [],
1461 'rules': [
1462 'per-file %s=set noparent' % pattern,
1463 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1464 ]
1465 }
1466 to_check[owners_file][pattern]['files'].append(f)
1467 break
1468
1469 # Now go through the OWNERS files we collected, filtering out rules that are
1470 # already present in that OWNERS file.
1471 for owners_file, patterns in to_check.iteritems():
1472 try:
1473 with file(owners_file) as f:
1474 lines = set(f.read().splitlines())
1475 for entry in patterns.itervalues():
1476 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1477 ]
1478 except IOError:
1479 # No OWNERS file, so all the rules are definitely missing.
1480 continue
1481
1482 # All the remaining lines weren't found in OWNERS files, so emit an error.
1483 errors = []
1484 for owners_file, patterns in to_check.iteritems():
1485 missing_lines = []
1486 files = []
1487 for pattern, entry in patterns.iteritems():
1488 missing_lines.extend(entry['rules'])
1489 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1490 if missing_lines:
1491 errors.append(
1492 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1493 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1494
1495 results = []
1496 if errors:
1497 results.append(output_api.PresubmitError(
1498 'Found changes to IPC files without a security OWNER!',
1499 long_text='\n\n'.join(errors)))
1500
1501 return results
1502
1503
dskiba88634f4e2015-08-14 23:03:291504def _CheckAndroidToastUsage(input_api, output_api):
1505 """Checks that code uses org.chromium.ui.widget.Toast instead of
1506 android.widget.Toast (Chromium Toast doesn't force hardware
1507 acceleration on low-end devices, saving memory).
1508 """
1509 toast_import_pattern = input_api.re.compile(
1510 r'^import android\.widget\.Toast;$')
1511
1512 errors = []
1513
1514 sources = lambda affected_file: input_api.FilterSourceFile(
1515 affected_file,
1516 black_list=(_EXCLUDED_PATHS +
1517 _TEST_CODE_EXCLUDED_PATHS +
1518 input_api.DEFAULT_BLACK_LIST +
1519 (r'^chromecast[\\\/].*',
1520 r'^remoting[\\\/].*')),
1521 white_list=(r'.*\.java$',))
1522
1523 for f in input_api.AffectedSourceFiles(sources):
1524 for line_num, line in f.ChangedContents():
1525 if toast_import_pattern.search(line):
1526 errors.append("%s:%d" % (f.LocalPath(), line_num))
1527
1528 results = []
1529
1530 if errors:
1531 results.append(output_api.PresubmitError(
1532 'android.widget.Toast usage is detected. Android toasts use hardware'
1533 ' acceleration, and can be\ncostly on low-end devices. Please use'
1534 ' org.chromium.ui.widget.Toast instead.\n'
1535 'Contact [email protected] if you have any questions.',
1536 errors))
1537
1538 return results
1539
1540
dgnaa68d5e2015-06-10 10:08:221541def _CheckAndroidCrLogUsage(input_api, output_api):
1542 """Checks that new logs using org.chromium.base.Log:
1543 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511544 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221545 """
pkotwicza1dd0b002016-05-16 14:41:041546
1547 # Do not check format of logs in //chrome/android/webapk because
1548 # //chrome/android/webapk cannot depend on //base
1549 cr_log_check_excluded_paths = [
1550 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1551 ]
1552
dgnaa68d5e2015-06-10 10:08:221553 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121554 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1555 class_in_base_pattern = input_api.re.compile(
1556 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1557 has_some_log_import_pattern = input_api.re.compile(
1558 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221559 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121560 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221561 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511562 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221563 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221564
Vincent Scheib16d7b272015-09-15 18:09:071565 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221566 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041567 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1568 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121569
dgnaa68d5e2015-06-10 10:08:221570 tag_decl_errors = []
1571 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121572 tag_errors = []
dgn38736db2015-09-18 19:20:511573 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121574 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221575
1576 for f in input_api.AffectedSourceFiles(sources):
1577 file_content = input_api.ReadFile(f)
1578 has_modified_logs = False
1579
1580 # Per line checks
dgn87d9fb62015-06-12 09:15:121581 if (cr_log_import_pattern.search(file_content) or
1582 (class_in_base_pattern.search(file_content) and
1583 not has_some_log_import_pattern.search(file_content))):
1584 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221585 for line_num, line in f.ChangedContents():
1586
1587 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121588 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221589 if match:
1590 has_modified_logs = True
1591
1592 # Make sure it uses "TAG"
1593 if not match.group('tag') == 'TAG':
1594 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121595 else:
1596 # Report non cr Log function calls in changed lines
1597 for line_num, line in f.ChangedContents():
1598 if log_call_pattern.search(line):
1599 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221600
1601 # Per file checks
1602 if has_modified_logs:
1603 # Make sure the tag is using the "cr" prefix and is not too long
1604 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511605 tag_name = match.group('name') if match else None
1606 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221607 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511608 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221609 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511610 elif '.' in tag_name:
1611 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221612
1613 results = []
1614 if tag_decl_errors:
1615 results.append(output_api.PresubmitPromptWarning(
1616 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511617 '"private static final String TAG = "<package tag>".\n'
1618 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221619 tag_decl_errors))
1620
1621 if tag_length_errors:
1622 results.append(output_api.PresubmitError(
1623 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511624 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221625 tag_length_errors))
1626
1627 if tag_errors:
1628 results.append(output_api.PresubmitPromptWarning(
1629 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1630 tag_errors))
1631
dgn87d9fb62015-06-12 09:15:121632 if util_log_errors:
dgn4401aa52015-04-29 16:26:171633 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121634 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1635 util_log_errors))
1636
dgn38736db2015-09-18 19:20:511637 if tag_with_dot_errors:
1638 results.append(output_api.PresubmitPromptWarning(
1639 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1640 tag_with_dot_errors))
1641
dgn4401aa52015-04-29 16:26:171642 return results
1643
1644
agrieve7b6479d82015-10-07 14:24:221645def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1646 """Checks if MDPI assets are placed in a correct directory."""
1647 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1648 ('/res/drawable/' in f.LocalPath() or
1649 '/res/drawable-ldrtl/' in f.LocalPath()))
1650 errors = []
1651 for f in input_api.AffectedFiles(include_deletes=False,
1652 file_filter=file_filter):
1653 errors.append(' %s' % f.LocalPath())
1654
1655 results = []
1656 if errors:
1657 results.append(output_api.PresubmitError(
1658 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1659 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1660 '/res/drawable-ldrtl/.\n'
1661 'Contact [email protected] if you have questions.', errors))
1662 return results
1663
1664
agrievef32bcc72016-04-04 14:57:401665class PydepsChecker(object):
1666 def __init__(self, input_api, pydeps_files):
1667 self._file_cache = {}
1668 self._input_api = input_api
1669 self._pydeps_files = pydeps_files
1670
1671 def _LoadFile(self, path):
1672 """Returns the list of paths within a .pydeps file relative to //."""
1673 if path not in self._file_cache:
1674 with open(path) as f:
1675 self._file_cache[path] = f.read()
1676 return self._file_cache[path]
1677
1678 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1679 """Returns an interable of paths within the .pydep, relativized to //."""
1680 os_path = self._input_api.os_path
1681 pydeps_dir = os_path.dirname(pydeps_path)
1682 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1683 if not l.startswith('*'))
1684 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1685
1686 def _CreateFilesToPydepsMap(self):
1687 """Returns a map of local_path -> list_of_pydeps."""
1688 ret = {}
1689 for pydep_local_path in self._pydeps_files:
1690 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1691 ret.setdefault(path, []).append(pydep_local_path)
1692 return ret
1693
1694 def ComputeAffectedPydeps(self):
1695 """Returns an iterable of .pydeps files that might need regenerating."""
1696 affected_pydeps = set()
1697 file_to_pydeps_map = None
1698 for f in self._input_api.AffectedFiles(include_deletes=True):
1699 local_path = f.LocalPath()
1700 if local_path == 'DEPS':
1701 return self._pydeps_files
1702 elif local_path.endswith('.pydeps'):
1703 if local_path in self._pydeps_files:
1704 affected_pydeps.add(local_path)
1705 elif local_path.endswith('.py'):
1706 if file_to_pydeps_map is None:
1707 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1708 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1709 return affected_pydeps
1710
1711 def DetermineIfStale(self, pydeps_path):
1712 """Runs print_python_deps.py to see if the files is stale."""
1713 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1714 cmd = old_pydeps_data[1][1:].strip()
1715 new_pydeps_data = self._input_api.subprocess.check_output(
1716 cmd + ' --output ""', shell=True)
1717 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
1718 return cmd
1719
1720
1721def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1722 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001723 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281724 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1725 # Mac, so skip it on other platforms.
1726 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001727 return []
agrievef32bcc72016-04-04 14:57:401728 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1729 is_android = input_api.os_path.exists('third_party/android_tools')
1730 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1731 results = []
1732 # First, check for new / deleted .pydeps.
1733 for f in input_api.AffectedFiles(include_deletes=True):
1734 if f.LocalPath().endswith('.pydeps'):
1735 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1736 results.append(output_api.PresubmitError(
1737 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1738 'remove %s' % f.LocalPath()))
1739 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1740 results.append(output_api.PresubmitError(
1741 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1742 'include %s' % f.LocalPath()))
1743
1744 if results:
1745 return results
1746
1747 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1748
1749 for pydep_path in checker.ComputeAffectedPydeps():
1750 try:
1751 cmd = checker.DetermineIfStale(pydep_path)
1752 if cmd:
1753 results.append(output_api.PresubmitError(
1754 'File is stale: %s\nTo regenerate, run:\n\n %s' %
1755 (pydep_path, cmd)))
1756 except input_api.subprocess.CalledProcessError as error:
1757 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1758 long_text=error.output)]
1759
1760 return results
1761
1762
mnaganov9b9b1fe82014-12-11 16:30:361763def _CheckForCopyrightedCode(input_api, output_api):
1764 """Verifies that newly added code doesn't contain copyrighted material
1765 and is properly licensed under the standard Chromium license.
1766
1767 As there can be false positives, we maintain a whitelist file. This check
1768 also verifies that the whitelist file is up to date.
1769 """
1770 import sys
1771 original_sys_path = sys.path
1772 try:
1773 sys.path = sys.path + [input_api.os_path.join(
mnaganovf771be4a2015-06-12 18:13:221774 input_api.PresubmitLocalPath(), 'tools')]
1775 from copyright_scanner import copyright_scanner
mnaganov9b9b1fe82014-12-11 16:30:361776 finally:
1777 # Restore sys.path to what it was before.
1778 sys.path = original_sys_path
1779
1780 return copyright_scanner.ScanAtPresubmit(input_api, output_api)
1781
1782
glidere61efad2015-02-18 17:39:431783def _CheckSingletonInHeaders(input_api, output_api):
1784 """Checks to make sure no header files have |Singleton<|."""
1785 def FileFilter(affected_file):
1786 # It's ok for base/memory/singleton.h to have |Singleton<|.
1787 black_list = (_EXCLUDED_PATHS +
1788 input_api.DEFAULT_BLACK_LIST +
1789 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1790 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1791
sergeyu34d21222015-09-16 00:11:441792 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431793 files = []
1794 for f in input_api.AffectedSourceFiles(FileFilter):
1795 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1796 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1797 contents = input_api.ReadFile(f)
1798 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241799 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431800 pattern.search(line)):
1801 files.append(f)
1802 break
1803
1804 if files:
yolandyandaabc6d2016-04-18 18:29:391805 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441806 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431807 'Please move them to an appropriate source file so that the ' +
1808 'template gets instantiated in a single compilation unit.',
1809 files) ]
1810 return []
1811
1812
dbeam37e8e7402016-02-10 22:58:201813def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1814 """Checks for old style compiled_resources.gyp files."""
1815 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1816
1817 added_compiled_resources = filter(is_compiled_resource, [
1818 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1819 ])
1820
1821 if not added_compiled_resources:
1822 return []
1823
1824 return [output_api.PresubmitError(
1825 "Found new compiled_resources.gyp files:\n%s\n\n"
1826 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551827 "please use compiled_resources2.gyp instead:\n"
1828 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1829 %
dbeam37e8e7402016-02-10 22:58:201830 "\n".join(added_compiled_resources))]
1831
1832
[email protected]fd20b902014-05-09 02:14:531833_DEPRECATED_CSS = [
1834 # Values
1835 ( "-webkit-box", "flex" ),
1836 ( "-webkit-inline-box", "inline-flex" ),
1837 ( "-webkit-flex", "flex" ),
1838 ( "-webkit-inline-flex", "inline-flex" ),
1839 ( "-webkit-min-content", "min-content" ),
1840 ( "-webkit-max-content", "max-content" ),
1841
1842 # Properties
1843 ( "-webkit-background-clip", "background-clip" ),
1844 ( "-webkit-background-origin", "background-origin" ),
1845 ( "-webkit-background-size", "background-size" ),
1846 ( "-webkit-box-shadow", "box-shadow" ),
1847
1848 # Functions
1849 ( "-webkit-gradient", "gradient" ),
1850 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1851 ( "-webkit-linear-gradient", "linear-gradient" ),
1852 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1853 ( "-webkit-radial-gradient", "radial-gradient" ),
1854 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1855]
1856
1857def _CheckNoDeprecatedCSS(input_api, output_api):
1858 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251859 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341860 documentation and iOS CSS for dom distiller
1861 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251862 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531863 results = []
dbeam070cfe62014-10-22 06:44:021864 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251865 black_list = (_EXCLUDED_PATHS +
1866 _TEST_CODE_EXCLUDED_PATHS +
1867 input_api.DEFAULT_BLACK_LIST +
1868 (r"^chrome/common/extensions/docs",
1869 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341870 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051871 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441872 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251873 r"^native_client_sdk"))
1874 file_filter = lambda f: input_api.FilterSourceFile(
1875 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531876 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1877 for line_num, line in fpath.ChangedContents():
1878 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021879 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531880 results.append(output_api.PresubmitError(
1881 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1882 (fpath.LocalPath(), line_num, deprecated_value, value)))
1883 return results
1884
mohan.reddyf21db962014-10-16 12:26:471885
dbeam070cfe62014-10-22 06:44:021886_DEPRECATED_JS = [
1887 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1888 ( "__defineGetter__", "Object.defineProperty" ),
1889 ( "__defineSetter__", "Object.defineProperty" ),
1890]
1891
1892def _CheckNoDeprecatedJS(input_api, output_api):
1893 """Make sure that we don't use deprecated JS in Chrome code."""
1894 results = []
1895 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1896 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1897 input_api.DEFAULT_BLACK_LIST)
1898 file_filter = lambda f: input_api.FilterSourceFile(
1899 f, white_list=file_inclusion_pattern, black_list=black_list)
1900 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1901 for lnum, line in fpath.ChangedContents():
1902 for (deprecated, replacement) in _DEPRECATED_JS:
1903 if deprecated in line:
1904 results.append(output_api.PresubmitError(
1905 "%s:%d: Use of deprecated JS %s, use %s instead" %
1906 (fpath.LocalPath(), lnum, deprecated, replacement)))
1907 return results
1908
1909
dgnaa68d5e2015-06-10 10:08:221910def _AndroidSpecificOnUploadChecks(input_api, output_api):
1911 """Groups checks that target android code."""
1912 results = []
dgnaa68d5e2015-06-10 10:08:221913 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221914 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291915 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221916 return results
1917
1918
[email protected]22c9bd72011-03-27 16:47:391919def _CommonChecks(input_api, output_api):
1920 """Checks common to both upload and commit."""
1921 results = []
1922 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381923 input_api, output_api,
1924 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461925 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191926 results.extend(
[email protected]760deea2013-12-10 19:33:491927 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541928 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181929 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521930 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:221931 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:441932 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:591933 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:061934 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:121935 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:181936 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:221937 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:491938 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:271939 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:031940 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:491941 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:441942 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:271943 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:541944 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:441945 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:391946 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:551947 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:041948 results.extend(
1949 input_api.canned_checks.CheckChangeHasNoTabs(
1950 input_api,
1951 output_api,
1952 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:401953 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:161954 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:591955 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:081956 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:531957 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:021958 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:471959 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:041960 results.extend(_CheckForIPCRules(input_api, output_api))
mnaganov9b9b1fe82014-12-11 16:30:361961 results.extend(_CheckForCopyrightedCode(input_api, output_api))
mostynbb639aca52015-01-07 20:31:231962 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:431963 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:201964 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
agrievef32bcc72016-04-04 14:57:401965 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:151966 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:171967 results.extend(_CheckIpcOwners(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:241968
1969 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
1970 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
1971 input_api, output_api,
1972 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:381973 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:391974 return results
[email protected]1f7b4172010-01-28 01:17:341975
[email protected]b337cb5b2011-01-23 21:24:051976
[email protected]66daa702011-05-28 14:41:461977def _CheckAuthorizedAuthor(input_api, output_api):
1978 """For non-googler/chromites committers, verify the author's email address is
1979 in AUTHORS.
1980 """
1981 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:011982 if not author:
1983 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:461984 return []
[email protected]c99663292011-05-31 19:46:081985 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:461986 input_api.PresubmitLocalPath(), 'AUTHORS')
1987 valid_authors = (
1988 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
1989 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:181990 valid_authors = [item.group(1).lower() for item in valid_authors if item]
dchenge07de812016-06-20 19:27:171991 if not any(input_api.fnmatch.fnmatch(author.lower(), valid)
1992 for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:231993 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:461994 return [output_api.PresubmitPromptWarning(
1995 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
1996 '\n'
1997 'http://www.chromium.org/developers/contributing-code and read the '
1998 '"Legal" section\n'
1999 'If you are a chromite, verify the contributor signed the CLA.') %
2000 author)]
2001 return []
2002
2003
[email protected]b8079ae4a2012-12-05 19:56:492004def _CheckPatchFiles(input_api, output_api):
2005 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2006 if f.LocalPath().endswith(('.orig', '.rej'))]
2007 if problems:
2008 return [output_api.PresubmitError(
2009 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032010 else:
2011 return []
[email protected]b8079ae4a2012-12-05 19:56:492012
2013
[email protected]b00342e7f2013-03-26 16:21:542014def _DidYouMeanOSMacro(bad_macro):
2015 try:
2016 return {'A': 'OS_ANDROID',
2017 'B': 'OS_BSD',
2018 'C': 'OS_CHROMEOS',
2019 'F': 'OS_FREEBSD',
2020 'L': 'OS_LINUX',
2021 'M': 'OS_MACOSX',
2022 'N': 'OS_NACL',
2023 'O': 'OS_OPENBSD',
2024 'P': 'OS_POSIX',
2025 'S': 'OS_SOLARIS',
2026 'W': 'OS_WIN'}[bad_macro[3].upper()]
2027 except KeyError:
2028 return ''
2029
2030
2031def _CheckForInvalidOSMacrosInFile(input_api, f):
2032 """Check for sensible looking, totally invalid OS macros."""
2033 preprocessor_statement = input_api.re.compile(r'^\s*#')
2034 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2035 results = []
2036 for lnum, line in f.ChangedContents():
2037 if preprocessor_statement.search(line):
2038 for match in os_macro.finditer(line):
2039 if not match.group(1) in _VALID_OS_MACROS:
2040 good = _DidYouMeanOSMacro(match.group(1))
2041 did_you_mean = ' (did you mean %s?)' % good if good else ''
2042 results.append(' %s:%d %s%s' % (f.LocalPath(),
2043 lnum,
2044 match.group(1),
2045 did_you_mean))
2046 return results
2047
2048
2049def _CheckForInvalidOSMacros(input_api, output_api):
2050 """Check all affected files for invalid OS macros."""
2051 bad_macros = []
2052 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472053 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542054 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2055
2056 if not bad_macros:
2057 return []
2058
2059 return [output_api.PresubmitError(
2060 'Possibly invalid OS macro[s] found. Please fix your code\n'
2061 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2062
lliabraa35bab3932014-10-01 12:16:442063
2064def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2065 """Check all affected files for invalid "if defined" macros."""
2066 ALWAYS_DEFINED_MACROS = (
2067 "TARGET_CPU_PPC",
2068 "TARGET_CPU_PPC64",
2069 "TARGET_CPU_68K",
2070 "TARGET_CPU_X86",
2071 "TARGET_CPU_ARM",
2072 "TARGET_CPU_MIPS",
2073 "TARGET_CPU_SPARC",
2074 "TARGET_CPU_ALPHA",
2075 "TARGET_IPHONE_SIMULATOR",
2076 "TARGET_OS_EMBEDDED",
2077 "TARGET_OS_IPHONE",
2078 "TARGET_OS_MAC",
2079 "TARGET_OS_UNIX",
2080 "TARGET_OS_WIN32",
2081 )
2082 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2083 results = []
2084 for lnum, line in f.ChangedContents():
2085 for match in ifdef_macro.finditer(line):
2086 if match.group(1) in ALWAYS_DEFINED_MACROS:
2087 always_defined = ' %s is always defined. ' % match.group(1)
2088 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2089 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2090 lnum,
2091 always_defined,
2092 did_you_mean))
2093 return results
2094
2095
2096def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2097 """Check all affected files for invalid "if defined" macros."""
2098 bad_macros = []
2099 for f in input_api.AffectedFiles():
2100 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2101 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2102
2103 if not bad_macros:
2104 return []
2105
2106 return [output_api.PresubmitError(
2107 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2108 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2109 bad_macros)]
2110
2111
mlamouria82272622014-09-16 18:45:042112def _CheckForIPCRules(input_api, output_api):
2113 """Check for same IPC rules described in
2114 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2115 """
2116 base_pattern = r'IPC_ENUM_TRAITS\('
2117 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2118 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2119
2120 problems = []
2121 for f in input_api.AffectedSourceFiles(None):
2122 local_path = f.LocalPath()
2123 if not local_path.endswith('.h'):
2124 continue
2125 for line_number, line in f.ChangedContents():
2126 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2127 problems.append(
2128 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2129
2130 if problems:
2131 return [output_api.PresubmitPromptWarning(
2132 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2133 else:
2134 return []
2135
[email protected]b00342e7f2013-03-26 16:21:542136
mostynbb639aca52015-01-07 20:31:232137def _CheckForWindowsLineEndings(input_api, output_api):
2138 """Check source code and known ascii text files for Windows style line
2139 endings.
2140 """
earthdok1b5e0ee2015-03-10 15:19:102141 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232142
2143 file_inclusion_pattern = (
2144 known_text_files,
2145 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2146 )
2147
2148 filter = lambda f: input_api.FilterSourceFile(
2149 f, white_list=file_inclusion_pattern, black_list=None)
2150 files = [f.LocalPath() for f in
2151 input_api.AffectedSourceFiles(filter)]
2152
2153 problems = []
2154
2155 for file in files:
2156 fp = open(file, 'r')
2157 for line in fp:
2158 if line.endswith('\r\n'):
2159 problems.append(file)
2160 break
2161 fp.close()
2162
2163 if problems:
2164 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2165 'these files to contain Windows style line endings?\n' +
2166 '\n'.join(problems))]
2167
2168 return []
2169
2170
[email protected]1f7b4172010-01-28 01:17:342171def CheckChangeOnUpload(input_api, output_api):
2172 results = []
2173 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472174 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282175 results.extend(
2176 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192177 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222178 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542179 return results
[email protected]ca8d1982009-02-19 16:33:122180
2181
[email protected]1bfb8322014-04-23 01:02:412182def GetTryServerMasterForBot(bot):
2183 """Returns the Try Server master for the given bot.
2184
[email protected]0bb112362014-07-26 04:38:322185 It tries to guess the master from the bot name, but may still fail
2186 and return None. There is no longer a default master.
2187 """
2188 # Potentially ambiguous bot names are listed explicitly.
2189 master_map = {
[email protected]0bb112362014-07-26 04:38:322190 'chromium_presubmit': 'tryserver.chromium.linux',
[email protected]0bb112362014-07-26 04:38:322191 'tools_build_presubmit': 'tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412192 }
[email protected]0bb112362014-07-26 04:38:322193 master = master_map.get(bot)
2194 if not master:
wnwen4fbaab82016-05-25 12:54:362195 if 'android' in bot:
2196 master = 'tryserver.chromium.android'
2197 elif 'linux' in bot or 'presubmit' in bot:
[email protected]0bb112362014-07-26 04:38:322198 master = 'tryserver.chromium.linux'
2199 elif 'win' in bot:
2200 master = 'tryserver.chromium.win'
2201 elif 'mac' in bot or 'ios' in bot:
2202 master = 'tryserver.chromium.mac'
2203 return master
[email protected]1bfb8322014-04-23 01:02:412204
2205
Paweł Hajdan, Jr55083782014-12-19 20:32:562206def GetDefaultTryConfigs(bots):
2207 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012208 """
2209
Paweł Hajdan, Jr55083782014-12-19 20:32:562210 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412211
2212 # Build up the mapping from tryserver master to bot/test.
2213 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562214 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412215 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2216 return out
[email protected]38c6a512013-12-18 23:48:012217
2218
[email protected]ca8d1982009-02-19 16:33:122219def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542220 results = []
[email protected]1f7b4172010-01-28 01:17:342221 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542222 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272223 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342224 input_api,
2225 output_api,
[email protected]2fdd1f362013-01-16 03:56:032226 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272227
[email protected]3e4eb112011-01-18 03:29:542228 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2229 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412230 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2231 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542232 return results