blob: 10f7ac06318b6b0854812c46a50ea6b27b99979e [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
jochen9ea8fdbc2014-09-25 13:21:3528# The NetscapePlugIn library is excluded from pan-project as it will soon
29# be deleted together with the rest of the NPAPI and it's not worthwhile to
30# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3831_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3232 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3833)
34
[email protected]06e6d0ff2012-12-11 01:36:4435# Fragment of a regular expression that matches C++ and Objective-C++
36# implementation files.
37_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
38
39# Regular expression that matches code only used for test binaries
40# (best effort).
41_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4942 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4443 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3244 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1245 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4446 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0548 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4949 r'content[\\\/]shell[\\\/].*',
[email protected]06e6d0ff2012-12-11 01:36:4450 # At request of folks maintaining this folder.
joaodasilva718f87672014-08-30 09:25:4951 r'chrome[\\\/]browser[\\\/]automation[\\\/].*',
[email protected]7b054982013-11-27 00:44:4752 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4953 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0854 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4955 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4456)
[email protected]ca8d1982009-02-19 16:33:1257
[email protected]eea609a2011-11-18 13:10:1258_TEST_ONLY_WARNING = (
59 'You might be calling functions intended only for testing from\n'
60 'production code. It is OK to ignore this warning if you know what\n'
61 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5862 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1263
64
[email protected]cf9b78f2012-11-14 11:40:2865_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4066 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2167 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
68 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2869
[email protected]127f18ec2012-06-16 05:05:5970_BANNED_OBJC_FUNCTIONS = (
71 (
72 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2073 (
74 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5975 'prohibited. Please use CrTrackingArea instead.',
76 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
77 ),
78 False,
79 ),
80 (
[email protected]eaae1972014-04-16 04:17:2681 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2082 (
83 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5984 'instead.',
85 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
86 ),
87 False,
88 ),
89 (
90 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2091 (
92 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5993 'Please use |convertPoint:(point) fromView:nil| instead.',
94 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
95 ),
96 True,
97 ),
98 (
99 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20100 (
101 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59102 'Please use |convertPoint:(point) toView:nil| instead.',
103 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
104 ),
105 True,
106 ),
107 (
108 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20109 (
110 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59111 'Please use |convertRect:(point) fromView:nil| instead.',
112 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
113 ),
114 True,
115 ),
116 (
117 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20118 (
119 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59120 'Please use |convertRect:(point) toView:nil| instead.',
121 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
122 ),
123 True,
124 ),
125 (
126 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20127 (
128 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59129 'Please use |convertSize:(point) fromView:nil| instead.',
130 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
131 ),
132 True,
133 ),
134 (
135 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20136 (
137 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59138 'Please use |convertSize:(point) toView:nil| instead.',
139 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
140 ),
141 True,
142 ),
143)
144
145
146_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20147 # Make sure that gtest's FRIEND_TEST() macro is not used; the
148 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30149 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20150 (
151 'FRIEND_TEST(',
152 (
[email protected]e3c945502012-06-26 20:01:49153 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20154 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
155 ),
156 False,
[email protected]7345da02012-11-27 14:31:49157 (),
[email protected]23e6cbc2012-06-16 18:51:20158 ),
159 (
160 'ScopedAllowIO',
161 (
[email protected]e3c945502012-06-26 20:01:49162 'New code should not use ScopedAllowIO. Post a task to the blocking',
163 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20164 ),
[email protected]e3c945502012-06-26 20:01:49165 True,
[email protected]7345da02012-11-27 14:31:49166 (
nyad2c548b2015-12-09 03:22:32167 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10168 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49169 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22170 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
alematee4016bb2014-11-12 17:38:51171 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
172 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09173 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49174 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
175 r"test_info_extractor\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41176 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
177 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
jamesra03ae492014-10-03 04:26:48178 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
179 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01180 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
[email protected]1f52a572014-05-12 23:21:54181 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
joedow91151042016-02-08 21:18:13182 r"^remoting[\\\/]host[\\\/]security_key[\\\/]"
183 "gnubby_auth_handler_linux\.cc$",
dnicoara171d8c82015-03-05 20:46:18184 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
rjkroege8471a0a92016-02-04 19:50:29185 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49186 ),
[email protected]23e6cbc2012-06-16 18:51:20187 ),
[email protected]52657f62013-05-20 05:30:31188 (
189 'SkRefPtr',
190 (
191 'The use of SkRefPtr is prohibited. ',
192 'Please use skia::RefPtr instead.'
193 ),
194 True,
195 (),
196 ),
197 (
198 'SkAutoRef',
199 (
200 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
201 'Please use skia::RefPtr instead.'
202 ),
203 True,
204 (),
205 ),
206 (
207 'SkAutoTUnref',
208 (
209 'The use of SkAutoTUnref is dangerous because it implicitly ',
210 'converts to a raw pointer. Please use skia::RefPtr instead.'
211 ),
212 True,
213 (),
214 ),
215 (
216 'SkAutoUnref',
217 (
218 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
219 'because it implicitly converts to a raw pointer. ',
220 'Please use skia::RefPtr instead.'
221 ),
222 True,
223 (),
224 ),
[email protected]d89eec82013-12-03 14:10:59225 (
226 r'/HANDLE_EINTR\(.*close',
227 (
228 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
229 'descriptor will be closed, and it is incorrect to retry the close.',
230 'Either call close directly and ignore its return value, or wrap close',
231 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
232 ),
233 True,
234 (),
235 ),
236 (
237 r'/IGNORE_EINTR\((?!.*close)',
238 (
239 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
240 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
241 ),
242 True,
243 (
244 # Files that #define IGNORE_EINTR.
245 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
246 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
247 ),
248 ),
[email protected]ec5b3f02014-04-04 18:43:43249 (
250 r'/v8::Extension\(',
251 (
252 'Do not introduce new v8::Extensions into the code base, use',
253 'gin::Wrappable instead. See http://crbug.com/334679',
254 ),
255 True,
[email protected]f55c90ee62014-04-12 00:50:03256 (
joaodasilva718f87672014-08-30 09:25:49257 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03258 ),
[email protected]ec5b3f02014-04-04 18:43:43259 ),
skyostilf9469f72015-04-20 10:38:52260 (
sdefresneeaeccc52015-04-22 08:18:32261 '\<MessageLoopProxy\>',
skyostilf9469f72015-04-20 10:38:52262 (
263 'MessageLoopProxy is deprecated. ',
264 'Please use SingleThreadTaskRunner or ThreadTaskRunnerHandle instead.'
265 ),
266 True,
kinuko59024ce2015-04-21 22:18:30267 (
268 # Internal message_loop related code may still use it.
269 r'^base[\\\/]message_loop[\\\/].*',
270 ),
skyostilf9469f72015-04-20 10:38:52271 ),
[email protected]127f18ec2012-06-16 05:05:59272)
273
mlamouria82272622014-09-16 18:45:04274_IPC_ENUM_TRAITS_DEPRECATED = (
275 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
276 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
277
[email protected]127f18ec2012-06-16 05:05:59278
[email protected]b00342e7f2013-03-26 16:21:54279_VALID_OS_MACROS = (
280 # Please keep sorted.
281 'OS_ANDROID',
282 'OS_BSD',
283 'OS_CAT', # For testing.
284 'OS_CHROMEOS',
285 'OS_FREEBSD',
286 'OS_IOS',
287 'OS_LINUX',
288 'OS_MACOSX',
289 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21290 'OS_NACL_NONSFI',
291 'OS_NACL_SFI',
[email protected]b00342e7f2013-03-26 16:21:54292 'OS_OPENBSD',
293 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37294 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54295 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54296 'OS_WIN',
297)
298
299
[email protected]55459852011-08-10 15:17:19300def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
301 """Attempts to prevent use of functions intended only for testing in
302 non-testing code. For now this is just a best-effort implementation
303 that ignores header files and may have some false positives. A
304 better implementation would probably need a proper C++ parser.
305 """
306 # We only scan .cc files and the like, as the declaration of
307 # for-testing functions in header files are hard to distinguish from
308 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44309 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19310
jochenc0d4808c2015-07-27 09:25:42311 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19312 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09313 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19314 exclusion_pattern = input_api.re.compile(
315 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
316 base_function_pattern, base_function_pattern))
317
318 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44319 black_list = (_EXCLUDED_PATHS +
320 _TEST_CODE_EXCLUDED_PATHS +
321 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19322 return input_api.FilterSourceFile(
323 affected_file,
324 white_list=(file_inclusion_pattern, ),
325 black_list=black_list)
326
327 problems = []
328 for f in input_api.AffectedSourceFiles(FilterFile):
329 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24330 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03331 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46332 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03333 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19334 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03335 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19336
337 if problems:
[email protected]f7051d52013-04-02 18:31:42338 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03339 else:
340 return []
[email protected]55459852011-08-10 15:17:19341
342
[email protected]10689ca2011-09-02 02:31:54343def _CheckNoIOStreamInHeaders(input_api, output_api):
344 """Checks to make sure no .h files include <iostream>."""
345 files = []
346 pattern = input_api.re.compile(r'^#include\s*<iostream>',
347 input_api.re.MULTILINE)
348 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
349 if not f.LocalPath().endswith('.h'):
350 continue
351 contents = input_api.ReadFile(f)
352 if pattern.search(contents):
353 files.append(f)
354
355 if len(files):
356 return [ output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06357 'Do not #include <iostream> in header files, since it inserts static '
358 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54359 '#include <ostream>. See http://crbug.com/94794',
360 files) ]
361 return []
362
363
[email protected]72df4e782012-06-21 16:28:18364def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52365 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18366 problems = []
367 for f in input_api.AffectedFiles():
368 if (not f.LocalPath().endswith(('.cc', '.mm'))):
369 continue
370
371 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04372 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18373 problems.append(' %s:%d' % (f.LocalPath(), line_num))
374
375 if not problems:
376 return []
377 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
378 '\n'.join(problems))]
379
380
danakj61c1aa22015-10-26 19:55:52381def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
382 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
383 errors = []
384 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
385 input_api.re.MULTILINE)
386 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
387 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
388 continue
389 for lnum, line in f.ChangedContents():
390 if input_api.re.search(pattern, line):
391 errors.append(output_api.PresubmitError(
392 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
393 'DCHECK_IS_ON()", not forgetting the braces.')
394 % (f.LocalPath(), lnum)))
395 return errors
396
397
mcasasb7440c282015-02-04 14:52:19398def _FindHistogramNameInLine(histogram_name, line):
399 """Tries to find a histogram name or prefix in a line."""
400 if not "affected-histogram" in line:
401 return histogram_name in line
402 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
403 # the histogram_name.
404 if not '"' in line:
405 return False
406 histogram_prefix = line.split('\"')[1]
407 return histogram_prefix in histogram_name
408
409
410def _CheckUmaHistogramChanges(input_api, output_api):
411 """Check that UMA histogram names in touched lines can still be found in other
412 lines of the patch or in histograms.xml. Note that this check would not catch
413 the reverse: changes in histograms.xml not matched in the code itself."""
414 touched_histograms = []
415 histograms_xml_modifications = []
416 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
417 for f in input_api.AffectedFiles():
418 # If histograms.xml itself is modified, keep the modified lines for later.
419 if f.LocalPath().endswith(('histograms.xml')):
420 histograms_xml_modifications = f.ChangedContents()
421 continue
422 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
423 continue
424 for line_num, line in f.ChangedContents():
425 found = pattern.search(line)
426 if found:
427 touched_histograms.append([found.group(1), f, line_num])
428
429 # Search for the touched histogram names in the local modifications to
430 # histograms.xml, and, if not found, on the base histograms.xml file.
431 unmatched_histograms = []
432 for histogram_info in touched_histograms:
433 histogram_name_found = False
434 for line_num, line in histograms_xml_modifications:
435 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
436 if histogram_name_found:
437 break
438 if not histogram_name_found:
439 unmatched_histograms.append(histogram_info)
440
eromanb90c82e7e32015-04-01 15:13:49441 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19442 problems = []
443 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49444 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19445 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45446 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19447 histogram_name_found = False
448 for line in histograms_xml:
449 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
450 if histogram_name_found:
451 break
452 if not histogram_name_found:
453 problems.append(' [%s:%d] %s' %
454 (f.LocalPath(), line_num, histogram_name))
455
456 if not problems:
457 return []
458 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
459 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49460 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19461
462
[email protected]8ea5d4b2011-09-13 21:49:22463def _CheckNoNewWStrings(input_api, output_api):
464 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27465 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22466 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20467 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57468 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
469 '/win/' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20470 continue
[email protected]8ea5d4b2011-09-13 21:49:22471
[email protected]a11dbe9b2012-08-07 01:32:58472 allowWString = False
[email protected]b5c24292011-11-28 14:38:20473 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58474 if 'presubmit: allow wstring' in line:
475 allowWString = True
476 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27477 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58478 allowWString = False
479 else:
480 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22481
[email protected]55463aa62011-10-12 00:48:27482 if not problems:
483 return []
484 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58485 ' If you are calling a cross-platform API that accepts a wstring, '
486 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27487 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22488
489
[email protected]2a8ac9c2011-10-19 17:20:44490def _CheckNoDEPSGIT(input_api, output_api):
491 """Make sure .DEPS.git is never modified manually."""
492 if any(f.LocalPath().endswith('.DEPS.git') for f in
493 input_api.AffectedFiles()):
494 return [output_api.PresubmitError(
495 'Never commit changes to .DEPS.git. This file is maintained by an\n'
496 'automated system based on what\'s in DEPS and your changes will be\n'
497 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34498 '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:44499 'for more information')]
500 return []
501
502
tandriief664692014-09-23 14:51:47503def _CheckValidHostsInDEPS(input_api, output_api):
504 """Checks that DEPS file deps are from allowed_hosts."""
505 # Run only if DEPS file has been modified to annoy fewer bystanders.
506 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
507 return []
508 # Outsource work to gclient verify
509 try:
510 input_api.subprocess.check_output(['gclient', 'verify'])
511 return []
512 except input_api.subprocess.CalledProcessError, error:
513 return [output_api.PresubmitError(
514 'DEPS file must have only git dependencies.',
515 long_text=error.output)]
516
517
[email protected]127f18ec2012-06-16 05:05:59518def _CheckNoBannedFunctions(input_api, output_api):
519 """Make sure that banned functions are not used."""
520 warnings = []
521 errors = []
522
523 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
524 for f in input_api.AffectedFiles(file_filter=file_filter):
525 for line_num, line in f.ChangedContents():
526 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
[email protected]eaae1972014-04-16 04:17:26527 matched = False
528 if func_name[0:1] == '/':
529 regex = func_name[1:]
530 if input_api.re.search(regex, line):
531 matched = True
532 elif func_name in line:
533 matched = True
534 if matched:
[email protected]127f18ec2012-06-16 05:05:59535 problems = warnings;
536 if error:
537 problems = errors;
538 problems.append(' %s:%d:' % (f.LocalPath(), line_num))
539 for message_line in message:
540 problems.append(' %s' % message_line)
541
542 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
543 for f in input_api.AffectedFiles(file_filter=file_filter):
544 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49545 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
546 def IsBlacklisted(affected_file, blacklist):
547 local_path = affected_file.LocalPath()
548 for item in blacklist:
549 if input_api.re.match(item, local_path):
550 return True
551 return False
552 if IsBlacklisted(f, excluded_paths):
553 continue
[email protected]d89eec82013-12-03 14:10:59554 matched = False
555 if func_name[0:1] == '/':
556 regex = func_name[1:]
557 if input_api.re.search(regex, line):
558 matched = True
559 elif func_name in line:
560 matched = True
561 if matched:
[email protected]127f18ec2012-06-16 05:05:59562 problems = warnings;
563 if error:
564 problems = errors;
565 problems.append(' %s:%d:' % (f.LocalPath(), line_num))
566 for message_line in message:
567 problems.append(' %s' % message_line)
568
569 result = []
570 if (warnings):
571 result.append(output_api.PresubmitPromptWarning(
572 'Banned functions were used.\n' + '\n'.join(warnings)))
573 if (errors):
574 result.append(output_api.PresubmitError(
575 'Banned functions were used.\n' + '\n'.join(errors)))
576 return result
577
578
[email protected]6c063c62012-07-11 19:11:06579def _CheckNoPragmaOnce(input_api, output_api):
580 """Make sure that banned functions are not used."""
581 files = []
582 pattern = input_api.re.compile(r'^#pragma\s+once',
583 input_api.re.MULTILINE)
584 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
585 if not f.LocalPath().endswith('.h'):
586 continue
587 contents = input_api.ReadFile(f)
588 if pattern.search(contents):
589 files.append(f)
590
591 if files:
592 return [output_api.PresubmitError(
593 'Do not use #pragma once in header files.\n'
594 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
595 files)]
596 return []
597
[email protected]127f18ec2012-06-16 05:05:59598
[email protected]e7479052012-09-19 00:26:12599def _CheckNoTrinaryTrueFalse(input_api, output_api):
600 """Checks to make sure we don't introduce use of foo ? true : false."""
601 problems = []
602 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
603 for f in input_api.AffectedFiles():
604 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
605 continue
606
607 for line_num, line in f.ChangedContents():
608 if pattern.match(line):
609 problems.append(' %s:%d' % (f.LocalPath(), line_num))
610
611 if not problems:
612 return []
613 return [output_api.PresubmitPromptWarning(
614 'Please consider avoiding the "? true : false" pattern if possible.\n' +
615 '\n'.join(problems))]
616
617
[email protected]55f9f382012-07-31 11:02:18618def _CheckUnwantedDependencies(input_api, output_api):
619 """Runs checkdeps on #include statements added in this
620 change. Breaking - rules is an error, breaking ! rules is a
621 warning.
622 """
mohan.reddyf21db962014-10-16 12:26:47623 import sys
[email protected]55f9f382012-07-31 11:02:18624 # We need to wait until we have an input_api object and use this
625 # roundabout construct to import checkdeps because this file is
626 # eval-ed and thus doesn't have __file__.
627 original_sys_path = sys.path
628 try:
629 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47630 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18631 import checkdeps
632 from cpp_checker import CppChecker
633 from rules import Rule
634 finally:
635 # Restore sys.path to what it was before.
636 sys.path = original_sys_path
637
638 added_includes = []
639 for f in input_api.AffectedFiles():
640 if not CppChecker.IsCppFile(f.LocalPath()):
641 continue
642
643 changed_lines = [line for line_num, line in f.ChangedContents()]
644 added_includes.append([f.LocalPath(), changed_lines])
645
[email protected]26385172013-05-09 23:11:35646 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18647
648 error_descriptions = []
649 warning_descriptions = []
650 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
651 added_includes):
652 description_with_path = '%s\n %s' % (path, rule_description)
653 if rule_type == Rule.DISALLOW:
654 error_descriptions.append(description_with_path)
655 else:
656 warning_descriptions.append(description_with_path)
657
658 results = []
659 if error_descriptions:
660 results.append(output_api.PresubmitError(
661 'You added one or more #includes that violate checkdeps rules.',
662 error_descriptions))
663 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42664 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18665 'You added one or more #includes of files that are temporarily\n'
666 'allowed but being removed. Can you avoid introducing the\n'
667 '#include? See relevant DEPS file(s) for details and contacts.',
668 warning_descriptions))
669 return results
670
671
[email protected]fbcafe5a2012-08-08 15:31:22672def _CheckFilePermissions(input_api, output_api):
673 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15674 if input_api.platform == 'win32':
675 return []
mohan.reddyf21db962014-10-16 12:26:47676 args = [input_api.python_executable, 'tools/checkperms/checkperms.py',
677 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22678 for f in input_api.AffectedFiles():
679 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11680 try:
681 input_api.subprocess.check_output(args)
682 return []
683 except input_api.subprocess.CalledProcessError as error:
684 return [output_api.PresubmitError(
685 'checkperms.py failed:',
686 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22687
688
[email protected]c8278b32012-10-30 20:35:49689def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
690 """Makes sure we don't include ui/aura/window_property.h
691 in header files.
692 """
693 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
694 errors = []
695 for f in input_api.AffectedFiles():
696 if not f.LocalPath().endswith('.h'):
697 continue
698 for line_num, line in f.ChangedContents():
699 if pattern.match(line):
700 errors.append(' %s:%d' % (f.LocalPath(), line_num))
701
702 results = []
703 if errors:
704 results.append(output_api.PresubmitError(
705 'Header files should not include ui/aura/window_property.h', errors))
706 return results
707
708
[email protected]cf9b78f2012-11-14 11:40:28709def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
710 """Checks that the lines in scope occur in the right order.
711
712 1. C system files in alphabetical order
713 2. C++ system files in alphabetical order
714 3. Project's .h files
715 """
716
717 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
718 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
719 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
720
721 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
722
723 state = C_SYSTEM_INCLUDES
724
725 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57726 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28727 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55728 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28729 for line_num, line in scope:
730 if c_system_include_pattern.match(line):
731 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55732 problem_linenums.append((line_num, previous_line_num,
733 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28734 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55735 problem_linenums.append((line_num, previous_line_num,
736 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28737 elif cpp_system_include_pattern.match(line):
738 if state == C_SYSTEM_INCLUDES:
739 state = CPP_SYSTEM_INCLUDES
740 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55741 problem_linenums.append((line_num, previous_line_num,
742 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28743 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55744 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28745 elif custom_include_pattern.match(line):
746 if state != CUSTOM_INCLUDES:
747 state = CUSTOM_INCLUDES
748 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55749 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28750 else:
brucedawson70fadb02015-06-30 17:47:55751 problem_linenums.append((line_num, previous_line_num,
752 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28753 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57754 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28755
756 warnings = []
brucedawson70fadb02015-06-30 17:47:55757 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57758 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55759 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28760 return warnings
761
762
[email protected]ac294a12012-12-06 16:38:43763def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28764 """Checks the #include order for the given file f."""
765
[email protected]2299dcf2012-11-15 19:56:24766 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30767 # Exclude the following includes from the check:
768 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
769 # specific order.
770 # 2) <atlbase.h>, "build/build_config.h"
771 excluded_include_pattern = input_api.re.compile(
772 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24773 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33774 # Match the final or penultimate token if it is xxxtest so we can ignore it
775 # when considering the special first include.
776 test_file_tag_pattern = input_api.re.compile(
777 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11778 if_pattern = input_api.re.compile(
779 r'\s*#\s*(if|elif|else|endif|define|undef).*')
780 # Some files need specialized order of includes; exclude such files from this
781 # check.
782 uncheckable_includes_pattern = input_api.re.compile(
783 r'\s*#include '
784 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28785
786 contents = f.NewContents()
787 warnings = []
788 line_num = 0
789
[email protected]ac294a12012-12-06 16:38:43790 # Handle the special first include. If the first include file is
791 # some/path/file.h, the corresponding including file can be some/path/file.cc,
792 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
793 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33794 # If the included file is some/path/file_platform.h the including file could
795 # also be some/path/file_xxxtest_platform.h.
796 including_file_base_name = test_file_tag_pattern.sub(
797 '', input_api.os_path.basename(f.LocalPath()))
798
[email protected]ac294a12012-12-06 16:38:43799 for line in contents:
800 line_num += 1
801 if system_include_pattern.match(line):
802 # No special first include -> process the line again along with normal
803 # includes.
804 line_num -= 1
805 break
806 match = custom_include_pattern.match(line)
807 if match:
808 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33809 header_basename = test_file_tag_pattern.sub(
810 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
811
812 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24813 # No special first include -> process the line again along with normal
814 # includes.
815 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43816 break
[email protected]cf9b78f2012-11-14 11:40:28817
818 # Split into scopes: Each region between #if and #endif is its own scope.
819 scopes = []
820 current_scope = []
821 for line in contents[line_num:]:
822 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11823 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54824 continue
[email protected]2309b0fa02012-11-16 12:18:27825 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28826 scopes.append(current_scope)
827 current_scope = []
[email protected]962f117e2012-11-22 18:11:56828 elif ((system_include_pattern.match(line) or
829 custom_include_pattern.match(line)) and
830 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28831 current_scope.append((line_num, line))
832 scopes.append(current_scope)
833
834 for scope in scopes:
835 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
836 changed_linenums))
837 return warnings
838
839
840def _CheckIncludeOrder(input_api, output_api):
841 """Checks that the #include order is correct.
842
843 1. The corresponding header for source files.
844 2. C system files in alphabetical order
845 3. C++ system files in alphabetical order
846 4. Project's .h files in alphabetical order
847
[email protected]ac294a12012-12-06 16:38:43848 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
849 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28850 """
[email protected]e120b012014-08-15 19:08:35851 def FileFilterIncludeOrder(affected_file):
852 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
853 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28854
855 warnings = []
[email protected]e120b012014-08-15 19:08:35856 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08857 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43858 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
859 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28860
861 results = []
862 if warnings:
[email protected]f7051d52013-04-02 18:31:42863 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53864 warnings))
[email protected]cf9b78f2012-11-14 11:40:28865 return results
866
867
[email protected]70ca77752012-11-20 03:45:03868def _CheckForVersionControlConflictsInFile(input_api, f):
869 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
870 errors = []
871 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23872 if f.LocalPath().endswith('.md'):
873 # First-level headers in markdown look a lot like version control
874 # conflict markers. http://daringfireball.net/projects/markdown/basics
875 continue
[email protected]70ca77752012-11-20 03:45:03876 if pattern.match(line):
877 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
878 return errors
879
880
881def _CheckForVersionControlConflicts(input_api, output_api):
882 """Usually this is not intentional and will cause a compile failure."""
883 errors = []
884 for f in input_api.AffectedFiles():
885 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
886
887 results = []
888 if errors:
889 results.append(output_api.PresubmitError(
890 'Version control conflict markers found, please resolve.', errors))
891 return results
892
893
[email protected]06e6d0ff2012-12-11 01:36:44894def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
895 def FilterFile(affected_file):
896 """Filter function for use with input_api.AffectedSourceFiles,
897 below. This filters out everything except non-test files from
898 top-level directories that generally speaking should not hard-code
899 service URLs (e.g. src/android_webview/, src/content/ and others).
900 """
901 return input_api.FilterSourceFile(
902 affected_file,
[email protected]78bb39d62012-12-11 15:11:56903 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44904 black_list=(_EXCLUDED_PATHS +
905 _TEST_CODE_EXCLUDED_PATHS +
906 input_api.DEFAULT_BLACK_LIST))
907
reillyi38965732015-11-16 18:27:33908 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
909 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:46910 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
911 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:44912 problems = [] # items are (filename, line_number, line)
913 for f in input_api.AffectedSourceFiles(FilterFile):
914 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:46915 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:44916 problems.append((f.LocalPath(), line_num, line))
917
918 if problems:
[email protected]f7051d52013-04-02 18:31:42919 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44920 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:58921 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:44922 [' %s:%d: %s' % (
923 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03924 else:
925 return []
[email protected]06e6d0ff2012-12-11 01:36:44926
927
[email protected]d2530012013-01-25 16:39:27928def _CheckNoAbbreviationInPngFileName(input_api, output_api):
929 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:31930 The native_client_sdk directory is excluded because it has auto-generated PNG
931 files for documentation.
[email protected]d2530012013-01-25 16:39:27932 """
[email protected]d2530012013-01-25 16:39:27933 errors = []
binji0dcdf342014-12-12 18:32:31934 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
935 black_list = (r'^native_client_sdk[\\\/]',)
936 file_filter = lambda f: input_api.FilterSourceFile(
937 f, white_list=white_list, black_list=black_list)
938 for f in input_api.AffectedFiles(include_deletes=False,
939 file_filter=file_filter):
940 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:27941
942 results = []
943 if errors:
944 results.append(output_api.PresubmitError(
945 'The name of PNG files should not have abbreviations. \n'
946 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
947 'Contact [email protected] if you have questions.', errors))
948 return results
949
950
[email protected]14a6131c2014-01-08 01:15:41951def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:08952 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:41953 a set of DEPS entries that we should look up.
954
955 For a directory (rather than a specific filename) we fake a path to
956 a specific filename by adding /DEPS. This is chosen as a file that
957 will seldom or never be subject to per-file include_rules.
958 """
[email protected]2b438d62013-11-14 17:54:14959 # We ignore deps entries on auto-generated directories.
960 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:08961
962 # This pattern grabs the path without basename in the first
963 # parentheses, and the basename (if present) in the second. It
964 # relies on the simple heuristic that if there is a basename it will
965 # be a header file ending in ".h".
966 pattern = re.compile(
967 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:14968 results = set()
[email protected]f32e2d1e2013-07-26 21:39:08969 for changed_line in changed_lines:
970 m = pattern.match(changed_line)
971 if m:
972 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:14973 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:41974 if m.group(2):
975 results.add('%s%s' % (path, m.group(2)))
976 else:
977 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:08978 return results
979
980
[email protected]e871964c2013-05-13 14:14:55981def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
982 """When a dependency prefixed with + is added to a DEPS file, we
983 want to make sure that the change is reviewed by an OWNER of the
984 target file or directory, to avoid layering violations from being
985 introduced. This check verifies that this happens.
986 """
987 changed_lines = set()
jochen53efcdd2016-01-29 05:09:24988
989 file_filter = lambda f: not input_api.re.match(
990 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
991 for f in input_api.AffectedFiles(include_deletes=False,
992 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:55993 filename = input_api.os_path.basename(f.LocalPath())
994 if filename == 'DEPS':
995 changed_lines |= set(line.strip()
996 for line_num, line
997 in f.ChangedContents())
998 if not changed_lines:
999 return []
1000
[email protected]14a6131c2014-01-08 01:15:411001 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1002 changed_lines)
[email protected]e871964c2013-05-13 14:14:551003 if not virtual_depended_on_files:
1004 return []
1005
1006 if input_api.is_committing:
1007 if input_api.tbr:
1008 return [output_api.PresubmitNotifyResult(
1009 '--tbr was specified, skipping OWNERS check for DEPS additions')]
1010 if not input_api.change.issue:
1011 return [output_api.PresubmitError(
1012 "DEPS approval by OWNERS check failed: this change has "
1013 "no Rietveld issue number, so we can't check it for approvals.")]
1014 output = output_api.PresubmitError
1015 else:
1016 output = output_api.PresubmitNotifyResult
1017
1018 owners_db = input_api.owners_db
1019 owner_email, reviewers = input_api.canned_checks._RietveldOwnerAndReviewers(
1020 input_api,
1021 owners_db.email_regexp,
1022 approval_needed=input_api.is_committing)
1023
1024 owner_email = owner_email or input_api.change.author_email
1025
[email protected]de4f7d22013-05-23 14:27:461026 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511027 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461028 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551029 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1030 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411031
1032 # We strip the /DEPS part that was added by
1033 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1034 # directory.
1035 def StripDeps(path):
1036 start_deps = path.rfind('/DEPS')
1037 if start_deps != -1:
1038 return path[:start_deps]
1039 else:
1040 return path
1041 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551042 for path in missing_files]
1043
1044 if unapproved_dependencies:
1045 output_list = [
[email protected]14a6131c2014-01-08 01:15:411046 output('Missing LGTM from OWNERS of dependencies added to DEPS:\n %s' %
[email protected]e871964c2013-05-13 14:14:551047 '\n '.join(sorted(unapproved_dependencies)))]
1048 if not input_api.is_committing:
1049 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1050 output_list.append(output(
1051 'Suggested missing target path OWNERS:\n %s' %
1052 '\n '.join(suggested_owners or [])))
1053 return output_list
1054
1055 return []
1056
1057
[email protected]85218562013-11-22 07:41:401058def _CheckSpamLogging(input_api, output_api):
1059 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1060 black_list = (_EXCLUDED_PATHS +
1061 _TEST_CODE_EXCLUDED_PATHS +
1062 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501063 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191064 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481065 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461066 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121067 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1068 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581069 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161070 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031071 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151072 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1073 r"^chromecast[\\\/]",
1074 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311075 r"^components[\\\/]html_viewer[\\\/]"
1076 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461077 # TODO(peter): Remove this exception. https://crbug.com/534537
1078 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1079 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251080 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1081 r"gl_helper_benchmark\.cc$",
thestigc9e38a22014-09-13 01:02:111082 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151083 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111084 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521085 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501086 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361087 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311088 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131089 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441090 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451091 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021092 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441093 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401094 source_file_filter = lambda x: input_api.FilterSourceFile(
1095 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1096
1097 log_info = []
1098 printf = []
1099
1100 for f in input_api.AffectedSourceFiles(source_file_filter):
1101 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471102 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401103 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471104 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131105 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371106
mohan.reddyf21db962014-10-16 12:26:471107 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371108 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471109 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401110 printf.append(f.LocalPath())
1111
1112 if log_info:
1113 return [output_api.PresubmitError(
1114 'These files spam the console log with LOG(INFO):',
1115 items=log_info)]
1116 if printf:
1117 return [output_api.PresubmitError(
1118 'These files spam the console log with printf/fprintf:',
1119 items=printf)]
1120 return []
1121
1122
[email protected]49aa76a2013-12-04 06:59:161123def _CheckForAnonymousVariables(input_api, output_api):
1124 """These types are all expected to hold locks while in scope and
1125 so should never be anonymous (which causes them to be immediately
1126 destroyed)."""
1127 they_who_must_be_named = [
1128 'base::AutoLock',
1129 'base::AutoReset',
1130 'base::AutoUnlock',
1131 'SkAutoAlphaRestore',
1132 'SkAutoBitmapShaderInstall',
1133 'SkAutoBlitterChoose',
1134 'SkAutoBounderCommit',
1135 'SkAutoCallProc',
1136 'SkAutoCanvasRestore',
1137 'SkAutoCommentBlock',
1138 'SkAutoDescriptor',
1139 'SkAutoDisableDirectionCheck',
1140 'SkAutoDisableOvalCheck',
1141 'SkAutoFree',
1142 'SkAutoGlyphCache',
1143 'SkAutoHDC',
1144 'SkAutoLockColors',
1145 'SkAutoLockPixels',
1146 'SkAutoMalloc',
1147 'SkAutoMaskFreeImage',
1148 'SkAutoMutexAcquire',
1149 'SkAutoPathBoundsUpdate',
1150 'SkAutoPDFRelease',
1151 'SkAutoRasterClipValidate',
1152 'SkAutoRef',
1153 'SkAutoTime',
1154 'SkAutoTrace',
1155 'SkAutoUnref',
1156 ]
1157 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1158 # bad: base::AutoLock(lock.get());
1159 # not bad: base::AutoLock lock(lock.get());
1160 bad_pattern = input_api.re.compile(anonymous)
1161 # good: new base::AutoLock(lock.get())
1162 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1163 errors = []
1164
1165 for f in input_api.AffectedFiles():
1166 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1167 continue
1168 for linenum, line in f.ChangedContents():
1169 if bad_pattern.search(line) and not good_pattern.search(line):
1170 errors.append('%s:%d' % (f.LocalPath(), linenum))
1171
1172 if errors:
1173 return [output_api.PresubmitError(
1174 'These lines create anonymous variables that need to be named:',
1175 items=errors)]
1176 return []
1177
1178
[email protected]5fe0f8742013-11-29 01:04:591179def _CheckCygwinShell(input_api, output_api):
1180 source_file_filter = lambda x: input_api.FilterSourceFile(
1181 x, white_list=(r'.+\.(gyp|gypi)$',))
1182 cygwin_shell = []
1183
1184 for f in input_api.AffectedSourceFiles(source_file_filter):
1185 for linenum, line in f.ChangedContents():
1186 if 'msvs_cygwin_shell' in line:
1187 cygwin_shell.append(f.LocalPath())
1188 break
1189
1190 if cygwin_shell:
1191 return [output_api.PresubmitError(
1192 'These files should not use msvs_cygwin_shell (the default is 0):',
1193 items=cygwin_shell)]
1194 return []
1195
[email protected]85218562013-11-22 07:41:401196
[email protected]999261d2014-03-03 20:08:081197def _CheckUserActionUpdate(input_api, output_api):
1198 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521199 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081200 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521201 # If actions.xml is already included in the changelist, the PRESUBMIT
1202 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081203 return []
1204
[email protected]999261d2014-03-03 20:08:081205 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1206 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521207 current_actions = None
[email protected]999261d2014-03-03 20:08:081208 for f in input_api.AffectedFiles(file_filter=file_filter):
1209 for line_num, line in f.ChangedContents():
1210 match = input_api.re.search(action_re, line)
1211 if match:
[email protected]2f92dec2014-03-07 19:21:521212 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1213 # loaded only once.
1214 if not current_actions:
1215 with open('tools/metrics/actions/actions.xml') as actions_f:
1216 current_actions = actions_f.read()
1217 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081218 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521219 action = 'name="{0}"'.format(action_name)
1220 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081221 return [output_api.PresubmitPromptWarning(
1222 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521223 'tools/metrics/actions/actions.xml. Please run '
1224 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081225 % (f.LocalPath(), line_num, action_name))]
1226 return []
1227
1228
[email protected]99171a92014-06-03 08:44:471229def _GetJSONParseError(input_api, filename, eat_comments=True):
1230 try:
1231 contents = input_api.ReadFile(filename)
1232 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131233 import sys
1234 original_sys_path = sys.path
1235 try:
1236 sys.path = sys.path + [input_api.os_path.join(
1237 input_api.PresubmitLocalPath(),
1238 'tools', 'json_comment_eater')]
1239 import json_comment_eater
1240 finally:
1241 sys.path = original_sys_path
1242 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471243
1244 input_api.json.loads(contents)
1245 except ValueError as e:
1246 return e
1247 return None
1248
1249
1250def _GetIDLParseError(input_api, filename):
1251 try:
1252 contents = input_api.ReadFile(filename)
1253 idl_schema = input_api.os_path.join(
1254 input_api.PresubmitLocalPath(),
1255 'tools', 'json_schema_compiler', 'idl_schema.py')
1256 process = input_api.subprocess.Popen(
1257 [input_api.python_executable, idl_schema],
1258 stdin=input_api.subprocess.PIPE,
1259 stdout=input_api.subprocess.PIPE,
1260 stderr=input_api.subprocess.PIPE,
1261 universal_newlines=True)
1262 (_, error) = process.communicate(input=contents)
1263 return error or None
1264 except ValueError as e:
1265 return e
1266
1267
1268def _CheckParseErrors(input_api, output_api):
1269 """Check that IDL and JSON files do not contain syntax errors."""
1270 actions = {
1271 '.idl': _GetIDLParseError,
1272 '.json': _GetJSONParseError,
1273 }
1274 # These paths contain test data and other known invalid JSON files.
1275 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491276 r'test[\\\/]data[\\\/]',
1277 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471278 ]
1279 # Most JSON files are preprocessed and support comments, but these do not.
1280 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491281 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471282 ]
1283 # Only run IDL checker on files in these directories.
1284 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491285 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1286 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471287 ]
1288
1289 def get_action(affected_file):
1290 filename = affected_file.LocalPath()
1291 return actions.get(input_api.os_path.splitext(filename)[1])
1292
1293 def MatchesFile(patterns, path):
1294 for pattern in patterns:
1295 if input_api.re.search(pattern, path):
1296 return True
1297 return False
1298
1299 def FilterFile(affected_file):
1300 action = get_action(affected_file)
1301 if not action:
1302 return False
1303 path = affected_file.LocalPath()
1304
1305 if MatchesFile(excluded_patterns, path):
1306 return False
1307
1308 if (action == _GetIDLParseError and
1309 not MatchesFile(idl_included_patterns, path)):
1310 return False
1311 return True
1312
1313 results = []
1314 for affected_file in input_api.AffectedFiles(
1315 file_filter=FilterFile, include_deletes=False):
1316 action = get_action(affected_file)
1317 kwargs = {}
1318 if (action == _GetJSONParseError and
1319 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1320 kwargs['eat_comments'] = False
1321 parse_error = action(input_api,
1322 affected_file.AbsoluteLocalPath(),
1323 **kwargs)
1324 if parse_error:
1325 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1326 (affected_file.LocalPath(), parse_error)))
1327 return results
1328
1329
[email protected]760deea2013-12-10 19:33:491330def _CheckJavaStyle(input_api, output_api):
1331 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471332 import sys
[email protected]760deea2013-12-10 19:33:491333 original_sys_path = sys.path
1334 try:
1335 sys.path = sys.path + [input_api.os_path.join(
1336 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1337 import checkstyle
1338 finally:
1339 # Restore sys.path to what it was before.
1340 sys.path = original_sys_path
1341
1342 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091343 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511344 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491345
1346
dskiba88634f4e2015-08-14 23:03:291347def _CheckAndroidToastUsage(input_api, output_api):
1348 """Checks that code uses org.chromium.ui.widget.Toast instead of
1349 android.widget.Toast (Chromium Toast doesn't force hardware
1350 acceleration on low-end devices, saving memory).
1351 """
1352 toast_import_pattern = input_api.re.compile(
1353 r'^import android\.widget\.Toast;$')
1354
1355 errors = []
1356
1357 sources = lambda affected_file: input_api.FilterSourceFile(
1358 affected_file,
1359 black_list=(_EXCLUDED_PATHS +
1360 _TEST_CODE_EXCLUDED_PATHS +
1361 input_api.DEFAULT_BLACK_LIST +
1362 (r'^chromecast[\\\/].*',
1363 r'^remoting[\\\/].*')),
1364 white_list=(r'.*\.java$',))
1365
1366 for f in input_api.AffectedSourceFiles(sources):
1367 for line_num, line in f.ChangedContents():
1368 if toast_import_pattern.search(line):
1369 errors.append("%s:%d" % (f.LocalPath(), line_num))
1370
1371 results = []
1372
1373 if errors:
1374 results.append(output_api.PresubmitError(
1375 'android.widget.Toast usage is detected. Android toasts use hardware'
1376 ' acceleration, and can be\ncostly on low-end devices. Please use'
1377 ' org.chromium.ui.widget.Toast instead.\n'
1378 'Contact [email protected] if you have any questions.',
1379 errors))
1380
1381 return results
1382
1383
dgnaa68d5e2015-06-10 10:08:221384def _CheckAndroidCrLogUsage(input_api, output_api):
1385 """Checks that new logs using org.chromium.base.Log:
1386 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511387 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221388 """
1389 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121390 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1391 class_in_base_pattern = input_api.re.compile(
1392 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1393 has_some_log_import_pattern = input_api.re.compile(
1394 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221395 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121396 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221397 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511398 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221399 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221400
Vincent Scheib16d7b272015-09-15 18:09:071401 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221402 'or contact [email protected] for more info.')
1403 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',))
dgn87d9fb62015-06-12 09:15:121404
dgnaa68d5e2015-06-10 10:08:221405 tag_decl_errors = []
1406 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121407 tag_errors = []
dgn38736db2015-09-18 19:20:511408 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121409 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221410
1411 for f in input_api.AffectedSourceFiles(sources):
1412 file_content = input_api.ReadFile(f)
1413 has_modified_logs = False
1414
1415 # Per line checks
dgn87d9fb62015-06-12 09:15:121416 if (cr_log_import_pattern.search(file_content) or
1417 (class_in_base_pattern.search(file_content) and
1418 not has_some_log_import_pattern.search(file_content))):
1419 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221420 for line_num, line in f.ChangedContents():
1421
1422 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121423 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221424 if match:
1425 has_modified_logs = True
1426
1427 # Make sure it uses "TAG"
1428 if not match.group('tag') == 'TAG':
1429 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121430 else:
1431 # Report non cr Log function calls in changed lines
1432 for line_num, line in f.ChangedContents():
1433 if log_call_pattern.search(line):
1434 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221435
1436 # Per file checks
1437 if has_modified_logs:
1438 # Make sure the tag is using the "cr" prefix and is not too long
1439 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511440 tag_name = match.group('name') if match else None
1441 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221442 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511443 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221444 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511445 elif '.' in tag_name:
1446 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221447
1448 results = []
1449 if tag_decl_errors:
1450 results.append(output_api.PresubmitPromptWarning(
1451 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511452 '"private static final String TAG = "<package tag>".\n'
1453 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221454 tag_decl_errors))
1455
1456 if tag_length_errors:
1457 results.append(output_api.PresubmitError(
1458 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511459 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221460 tag_length_errors))
1461
1462 if tag_errors:
1463 results.append(output_api.PresubmitPromptWarning(
1464 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1465 tag_errors))
1466
dgn87d9fb62015-06-12 09:15:121467 if util_log_errors:
dgn4401aa52015-04-29 16:26:171468 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121469 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1470 util_log_errors))
1471
dgn38736db2015-09-18 19:20:511472 if tag_with_dot_errors:
1473 results.append(output_api.PresubmitPromptWarning(
1474 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1475 tag_with_dot_errors))
1476
dgn4401aa52015-04-29 16:26:171477 return results
1478
1479
agrieve7b6479d82015-10-07 14:24:221480def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1481 """Checks if MDPI assets are placed in a correct directory."""
1482 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1483 ('/res/drawable/' in f.LocalPath() or
1484 '/res/drawable-ldrtl/' in f.LocalPath()))
1485 errors = []
1486 for f in input_api.AffectedFiles(include_deletes=False,
1487 file_filter=file_filter):
1488 errors.append(' %s' % f.LocalPath())
1489
1490 results = []
1491 if errors:
1492 results.append(output_api.PresubmitError(
1493 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1494 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1495 '/res/drawable-ldrtl/.\n'
1496 'Contact [email protected] if you have questions.', errors))
1497 return results
1498
1499
mnaganov9b9b1fe82014-12-11 16:30:361500def _CheckForCopyrightedCode(input_api, output_api):
1501 """Verifies that newly added code doesn't contain copyrighted material
1502 and is properly licensed under the standard Chromium license.
1503
1504 As there can be false positives, we maintain a whitelist file. This check
1505 also verifies that the whitelist file is up to date.
1506 """
1507 import sys
1508 original_sys_path = sys.path
1509 try:
1510 sys.path = sys.path + [input_api.os_path.join(
mnaganovf771be4a2015-06-12 18:13:221511 input_api.PresubmitLocalPath(), 'tools')]
1512 from copyright_scanner import copyright_scanner
mnaganov9b9b1fe82014-12-11 16:30:361513 finally:
1514 # Restore sys.path to what it was before.
1515 sys.path = original_sys_path
1516
1517 return copyright_scanner.ScanAtPresubmit(input_api, output_api)
1518
1519
glidere61efad2015-02-18 17:39:431520def _CheckSingletonInHeaders(input_api, output_api):
1521 """Checks to make sure no header files have |Singleton<|."""
1522 def FileFilter(affected_file):
1523 # It's ok for base/memory/singleton.h to have |Singleton<|.
1524 black_list = (_EXCLUDED_PATHS +
1525 input_api.DEFAULT_BLACK_LIST +
1526 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1527 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1528
sergeyu34d21222015-09-16 00:11:441529 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431530 files = []
1531 for f in input_api.AffectedSourceFiles(FileFilter):
1532 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1533 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1534 contents = input_api.ReadFile(f)
1535 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241536 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431537 pattern.search(line)):
1538 files.append(f)
1539 break
1540
1541 if files:
1542 return [ output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441543 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431544 'Please move them to an appropriate source file so that the ' +
1545 'template gets instantiated in a single compilation unit.',
1546 files) ]
1547 return []
1548
1549
dbeam37e8e7402016-02-10 22:58:201550def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1551 """Checks for old style compiled_resources.gyp files."""
1552 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1553
1554 added_compiled_resources = filter(is_compiled_resource, [
1555 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1556 ])
1557
1558 if not added_compiled_resources:
1559 return []
1560
1561 return [output_api.PresubmitError(
1562 "Found new compiled_resources.gyp files:\n%s\n\n"
1563 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551564 "please use compiled_resources2.gyp instead:\n"
1565 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1566 %
dbeam37e8e7402016-02-10 22:58:201567 "\n".join(added_compiled_resources))]
1568
1569
[email protected]fd20b902014-05-09 02:14:531570_DEPRECATED_CSS = [
1571 # Values
1572 ( "-webkit-box", "flex" ),
1573 ( "-webkit-inline-box", "inline-flex" ),
1574 ( "-webkit-flex", "flex" ),
1575 ( "-webkit-inline-flex", "inline-flex" ),
1576 ( "-webkit-min-content", "min-content" ),
1577 ( "-webkit-max-content", "max-content" ),
1578
1579 # Properties
1580 ( "-webkit-background-clip", "background-clip" ),
1581 ( "-webkit-background-origin", "background-origin" ),
1582 ( "-webkit-background-size", "background-size" ),
1583 ( "-webkit-box-shadow", "box-shadow" ),
1584
1585 # Functions
1586 ( "-webkit-gradient", "gradient" ),
1587 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1588 ( "-webkit-linear-gradient", "linear-gradient" ),
1589 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1590 ( "-webkit-radial-gradient", "radial-gradient" ),
1591 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1592]
1593
1594def _CheckNoDeprecatedCSS(input_api, output_api):
1595 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251596 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341597 documentation and iOS CSS for dom distiller
1598 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251599 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531600 results = []
dbeam070cfe62014-10-22 06:44:021601 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251602 black_list = (_EXCLUDED_PATHS +
1603 _TEST_CODE_EXCLUDED_PATHS +
1604 input_api.DEFAULT_BLACK_LIST +
1605 (r"^chrome/common/extensions/docs",
1606 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341607 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051608 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441609 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251610 r"^native_client_sdk"))
1611 file_filter = lambda f: input_api.FilterSourceFile(
1612 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531613 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1614 for line_num, line in fpath.ChangedContents():
1615 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021616 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531617 results.append(output_api.PresubmitError(
1618 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1619 (fpath.LocalPath(), line_num, deprecated_value, value)))
1620 return results
1621
mohan.reddyf21db962014-10-16 12:26:471622
dbeam070cfe62014-10-22 06:44:021623_DEPRECATED_JS = [
1624 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1625 ( "__defineGetter__", "Object.defineProperty" ),
1626 ( "__defineSetter__", "Object.defineProperty" ),
1627]
1628
1629def _CheckNoDeprecatedJS(input_api, output_api):
1630 """Make sure that we don't use deprecated JS in Chrome code."""
1631 results = []
1632 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1633 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1634 input_api.DEFAULT_BLACK_LIST)
1635 file_filter = lambda f: input_api.FilterSourceFile(
1636 f, white_list=file_inclusion_pattern, black_list=black_list)
1637 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1638 for lnum, line in fpath.ChangedContents():
1639 for (deprecated, replacement) in _DEPRECATED_JS:
1640 if deprecated in line:
1641 results.append(output_api.PresubmitError(
1642 "%s:%d: Use of deprecated JS %s, use %s instead" %
1643 (fpath.LocalPath(), lnum, deprecated, replacement)))
1644 return results
1645
1646
dgnaa68d5e2015-06-10 10:08:221647def _AndroidSpecificOnUploadChecks(input_api, output_api):
1648 """Groups checks that target android code."""
1649 results = []
dgnaa68d5e2015-06-10 10:08:221650 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221651 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291652 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221653 return results
1654
1655
[email protected]22c9bd72011-03-27 16:47:391656def _CommonChecks(input_api, output_api):
1657 """Checks common to both upload and commit."""
1658 results = []
1659 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381660 input_api, output_api,
1661 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461662 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191663 results.extend(
[email protected]760deea2013-12-10 19:33:491664 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541665 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181666 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521667 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:221668 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:441669 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:591670 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:061671 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:121672 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:181673 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:221674 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:491675 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:271676 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:031677 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:491678 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:441679 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:271680 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:541681 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:441682 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
danakj3c84d0c2014-10-06 15:35:461683 # TODO(danakj): Remove this when base/move.h is removed.
dchengcf95c122015-12-18 08:29:161684 results.extend(_CheckForUsingPass(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:551685 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:041686 results.extend(
1687 input_api.canned_checks.CheckChangeHasNoTabs(
1688 input_api,
1689 output_api,
1690 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:401691 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:161692 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:591693 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:081694 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:531695 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:021696 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:471697 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:041698 results.extend(_CheckForIPCRules(input_api, output_api))
mnaganov9b9b1fe82014-12-11 16:30:361699 results.extend(_CheckForCopyrightedCode(input_api, output_api))
mostynbb639aca52015-01-07 20:31:231700 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:431701 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:201702 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:241703
1704 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
1705 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
1706 input_api, output_api,
1707 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:381708 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:391709 return results
[email protected]1f7b4172010-01-28 01:17:341710
[email protected]b337cb5b2011-01-23 21:24:051711
[email protected]66daa702011-05-28 14:41:461712def _CheckAuthorizedAuthor(input_api, output_api):
1713 """For non-googler/chromites committers, verify the author's email address is
1714 in AUTHORS.
1715 """
[email protected]9bb9cb82011-06-13 20:43:011716 # TODO(maruel): Add it to input_api?
1717 import fnmatch
1718
[email protected]66daa702011-05-28 14:41:461719 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:011720 if not author:
1721 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:461722 return []
[email protected]c99663292011-05-31 19:46:081723 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:461724 input_api.PresubmitLocalPath(), 'AUTHORS')
1725 valid_authors = (
1726 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
1727 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:181728 valid_authors = [item.group(1).lower() for item in valid_authors if item]
[email protected]d8b50be2011-06-15 14:19:441729 if not any(fnmatch.fnmatch(author.lower(), valid) for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:231730 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:461731 return [output_api.PresubmitPromptWarning(
1732 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
1733 '\n'
1734 'http://www.chromium.org/developers/contributing-code and read the '
1735 '"Legal" section\n'
1736 'If you are a chromite, verify the contributor signed the CLA.') %
1737 author)]
1738 return []
1739
1740
[email protected]b8079ae4a2012-12-05 19:56:491741def _CheckPatchFiles(input_api, output_api):
1742 problems = [f.LocalPath() for f in input_api.AffectedFiles()
1743 if f.LocalPath().endswith(('.orig', '.rej'))]
1744 if problems:
1745 return [output_api.PresubmitError(
1746 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:031747 else:
1748 return []
[email protected]b8079ae4a2012-12-05 19:56:491749
1750
[email protected]b00342e7f2013-03-26 16:21:541751def _DidYouMeanOSMacro(bad_macro):
1752 try:
1753 return {'A': 'OS_ANDROID',
1754 'B': 'OS_BSD',
1755 'C': 'OS_CHROMEOS',
1756 'F': 'OS_FREEBSD',
1757 'L': 'OS_LINUX',
1758 'M': 'OS_MACOSX',
1759 'N': 'OS_NACL',
1760 'O': 'OS_OPENBSD',
1761 'P': 'OS_POSIX',
1762 'S': 'OS_SOLARIS',
1763 'W': 'OS_WIN'}[bad_macro[3].upper()]
1764 except KeyError:
1765 return ''
1766
1767
1768def _CheckForInvalidOSMacrosInFile(input_api, f):
1769 """Check for sensible looking, totally invalid OS macros."""
1770 preprocessor_statement = input_api.re.compile(r'^\s*#')
1771 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
1772 results = []
1773 for lnum, line in f.ChangedContents():
1774 if preprocessor_statement.search(line):
1775 for match in os_macro.finditer(line):
1776 if not match.group(1) in _VALID_OS_MACROS:
1777 good = _DidYouMeanOSMacro(match.group(1))
1778 did_you_mean = ' (did you mean %s?)' % good if good else ''
1779 results.append(' %s:%d %s%s' % (f.LocalPath(),
1780 lnum,
1781 match.group(1),
1782 did_you_mean))
1783 return results
1784
1785
1786def _CheckForInvalidOSMacros(input_api, output_api):
1787 """Check all affected files for invalid OS macros."""
1788 bad_macros = []
1789 for f in input_api.AffectedFiles():
1790 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css')):
1791 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
1792
1793 if not bad_macros:
1794 return []
1795
1796 return [output_api.PresubmitError(
1797 'Possibly invalid OS macro[s] found. Please fix your code\n'
1798 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
1799
lliabraa35bab3932014-10-01 12:16:441800
1801def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
1802 """Check all affected files for invalid "if defined" macros."""
1803 ALWAYS_DEFINED_MACROS = (
1804 "TARGET_CPU_PPC",
1805 "TARGET_CPU_PPC64",
1806 "TARGET_CPU_68K",
1807 "TARGET_CPU_X86",
1808 "TARGET_CPU_ARM",
1809 "TARGET_CPU_MIPS",
1810 "TARGET_CPU_SPARC",
1811 "TARGET_CPU_ALPHA",
1812 "TARGET_IPHONE_SIMULATOR",
1813 "TARGET_OS_EMBEDDED",
1814 "TARGET_OS_IPHONE",
1815 "TARGET_OS_MAC",
1816 "TARGET_OS_UNIX",
1817 "TARGET_OS_WIN32",
1818 )
1819 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
1820 results = []
1821 for lnum, line in f.ChangedContents():
1822 for match in ifdef_macro.finditer(line):
1823 if match.group(1) in ALWAYS_DEFINED_MACROS:
1824 always_defined = ' %s is always defined. ' % match.group(1)
1825 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
1826 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
1827 lnum,
1828 always_defined,
1829 did_you_mean))
1830 return results
1831
1832
1833def _CheckForInvalidIfDefinedMacros(input_api, output_api):
1834 """Check all affected files for invalid "if defined" macros."""
1835 bad_macros = []
1836 for f in input_api.AffectedFiles():
1837 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
1838 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
1839
1840 if not bad_macros:
1841 return []
1842
1843 return [output_api.PresubmitError(
1844 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
1845 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
1846 bad_macros)]
1847
1848
dchengcf95c122015-12-18 08:29:161849def _CheckForUsingPass(input_api, output_api):
danakj3c84d0c2014-10-06 15:35:461850 """Check all affected files for using side effects of Pass."""
1851 errors = []
1852 for f in input_api.AffectedFiles():
1853 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
1854 for lnum, line in f.ChangedContents():
dchengcf95c122015-12-18 08:29:161855 # Warn on any use of foo.Pass().
1856 if input_api.re.search(r'[a-zA-Z0-9_]+\.Pass\(\)', line):
danakj3c84d0c2014-10-06 15:35:461857 errors.append(output_api.PresubmitError(
dchengcf95c122015-12-18 08:29:161858 ('%s:%d uses Pass(); please use std::move() instead. ' +
1859 'See crbug.com/557422.') % (f.LocalPath(), lnum)))
danakj3c84d0c2014-10-06 15:35:461860 return errors
1861
1862
mlamouria82272622014-09-16 18:45:041863def _CheckForIPCRules(input_api, output_api):
1864 """Check for same IPC rules described in
1865 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
1866 """
1867 base_pattern = r'IPC_ENUM_TRAITS\('
1868 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
1869 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
1870
1871 problems = []
1872 for f in input_api.AffectedSourceFiles(None):
1873 local_path = f.LocalPath()
1874 if not local_path.endswith('.h'):
1875 continue
1876 for line_number, line in f.ChangedContents():
1877 if inclusion_pattern.search(line) and not comment_pattern.search(line):
1878 problems.append(
1879 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1880
1881 if problems:
1882 return [output_api.PresubmitPromptWarning(
1883 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
1884 else:
1885 return []
1886
[email protected]b00342e7f2013-03-26 16:21:541887
mostynbb639aca52015-01-07 20:31:231888def _CheckForWindowsLineEndings(input_api, output_api):
1889 """Check source code and known ascii text files for Windows style line
1890 endings.
1891 """
earthdok1b5e0ee2015-03-10 15:19:101892 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:231893
1894 file_inclusion_pattern = (
1895 known_text_files,
1896 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1897 )
1898
1899 filter = lambda f: input_api.FilterSourceFile(
1900 f, white_list=file_inclusion_pattern, black_list=None)
1901 files = [f.LocalPath() for f in
1902 input_api.AffectedSourceFiles(filter)]
1903
1904 problems = []
1905
1906 for file in files:
1907 fp = open(file, 'r')
1908 for line in fp:
1909 if line.endswith('\r\n'):
1910 problems.append(file)
1911 break
1912 fp.close()
1913
1914 if problems:
1915 return [output_api.PresubmitPromptWarning('Are you sure that you want '
1916 'these files to contain Windows style line endings?\n' +
1917 '\n'.join(problems))]
1918
1919 return []
1920
1921
[email protected]1f7b4172010-01-28 01:17:341922def CheckChangeOnUpload(input_api, output_api):
1923 results = []
1924 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:471925 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
aurimas8d3bc1c52014-10-15 01:02:171926 results.extend(_CheckJavaStyle(input_api, output_api))
scottmg39b29952014-12-08 18:31:281927 results.extend(
1928 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:191929 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221930 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:541931 return results
[email protected]ca8d1982009-02-19 16:33:121932
1933
[email protected]1bfb8322014-04-23 01:02:411934def GetTryServerMasterForBot(bot):
1935 """Returns the Try Server master for the given bot.
1936
[email protected]0bb112362014-07-26 04:38:321937 It tries to guess the master from the bot name, but may still fail
1938 and return None. There is no longer a default master.
1939 """
1940 # Potentially ambiguous bot names are listed explicitly.
1941 master_map = {
[email protected]0bb112362014-07-26 04:38:321942 'chromium_presubmit': 'tryserver.chromium.linux',
1943 'blink_presubmit': 'tryserver.chromium.linux',
1944 'tools_build_presubmit': 'tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:411945 }
[email protected]0bb112362014-07-26 04:38:321946 master = master_map.get(bot)
1947 if not master:
sergiyb37fd293f2015-02-26 06:55:011948 if 'linux' in bot or 'android' in bot or 'presubmit' in bot:
[email protected]0bb112362014-07-26 04:38:321949 master = 'tryserver.chromium.linux'
1950 elif 'win' in bot:
1951 master = 'tryserver.chromium.win'
1952 elif 'mac' in bot or 'ios' in bot:
1953 master = 'tryserver.chromium.mac'
1954 return master
[email protected]1bfb8322014-04-23 01:02:411955
1956
Paweł Hajdan, Jr55083782014-12-19 20:32:561957def GetDefaultTryConfigs(bots):
1958 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:011959 """
1960
Paweł Hajdan, Jr55083782014-12-19 20:32:561961 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:411962
1963 # Build up the mapping from tryserver master to bot/test.
1964 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:561965 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:411966 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
1967 return out
[email protected]38c6a512013-12-18 23:48:011968
1969
[email protected]ca8d1982009-02-19 16:33:121970def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:541971 results = []
[email protected]1f7b4172010-01-28 01:17:341972 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:541973 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:271974 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:341975 input_api,
1976 output_api,
[email protected]2fdd1f362013-01-16 03:56:031977 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:271978
[email protected]3e4eb112011-01-18 03:29:541979 results.extend(input_api.canned_checks.CheckChangeHasBugField(
1980 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:411981 results.extend(input_api.canned_checks.CheckChangeHasDescription(
1982 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:541983 return results