| # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
 | # Use of this source code is governed by a BSD-style license that can be | 
 | # found in the LICENSE file. | 
 |  | 
 | ANDROID_WHITELISTED_LICENSES = [ | 
 |   'A(pple )?PSL 2(\.0)?', | 
 |   'Apache( Version)? 2(\.0)?', | 
 |   '(New )?([23]-Clause )?BSD( [23]-Clause)?( with advertising clause)?', | 
 |   'L?GPL ?v?2(\.[01])?( or later)?', | 
 |   'MIT(/X11)?(-like)?', | 
 |   'MPL 1\.1 ?/ ?GPL 2(\.0)? ?/ ?LGPL 2\.1', | 
 |   'MPL 2(\.0)?', | 
 |   'Microsoft Limited Public License', | 
 |   'Microsoft Permissive License', | 
 |   'Public Domain', | 
 |   'Python', | 
 |   'SGI Free Software License B', | 
 |   'University of Illinois\/NCSA Open Source', | 
 |   'X11', | 
 | ] | 
 |  | 
 | def LicenseIsCompatibleWithAndroid(input_api, license): | 
 |   regex = '^(%s)$' % '|'.join(ANDROID_WHITELISTED_LICENSES) | 
 |   tokens = \ | 
 |     [x.strip() for x in input_api.re.split(' and |,', license) if len(x) > 0] | 
 |   has_compatible_license = False | 
 |   for token in tokens: | 
 |     if input_api.re.match(regex, token, input_api.re.IGNORECASE): | 
 |       has_compatible_license = True | 
 |       break | 
 |   return has_compatible_license | 
 |  | 
 | def _CheckThirdPartyReadmesUpdated(input_api, output_api): | 
 |   """ | 
 |   Checks to make sure that README.chromium files are properly updated | 
 |   when dependencies in third_party are modified. | 
 |   """ | 
 |   readmes = [] | 
 |   files = [] | 
 |   errors = [] | 
 |   for f in input_api.AffectedFiles(): | 
 |     local_path = f.LocalPath() | 
 |     if input_api.os_path.dirname(local_path) == 'third_party': | 
 |       continue | 
 |     if (local_path.startswith('third_party' + input_api.os_path.sep) and | 
 |         not local_path.startswith('third_party' + input_api.os_path.sep + | 
 |                                   'WebKit' + input_api.os_path.sep) and | 
 |         not local_path.startswith('third_party' + input_api.os_path.sep + | 
 |                                   'mojo' + input_api.os_path.sep) and | 
 |         not local_path.startswith('third_party' + input_api.os_path.sep + | 
 |                                   'boringssl' + input_api.os_path.sep)): | 
 |       files.append(f) | 
 |       if local_path.endswith("README.chromium"): | 
 |         readmes.append(f) | 
 |   if files and not readmes: | 
 |     errors.append(output_api.PresubmitPromptWarning( | 
 |        'When updating or adding third party code the appropriate\n' | 
 |        '\'README.chromium\' file should also be updated with the correct\n' | 
 |        'version and package information.', files)) | 
 |   if not readmes: | 
 |     return errors | 
 |  | 
 |   name_pattern = input_api.re.compile( | 
 |     r'^Name: [a-zA-Z0-9_\-\. \(\)]+\r?$', | 
 |     input_api.re.IGNORECASE | input_api.re.MULTILINE) | 
 |   shortname_pattern = input_api.re.compile( | 
 |     r'^Short Name: [a-zA-Z0-9_\-\.]+\r?$', | 
 |     input_api.re.IGNORECASE | input_api.re.MULTILINE) | 
 |   version_pattern = input_api.re.compile( | 
 |     r'^Version: [a-zA-Z0-9_\-\.:]+\r?$', | 
 |     input_api.re.IGNORECASE | input_api.re.MULTILINE) | 
 |   release_pattern = input_api.re.compile( | 
 |     r'^Security Critical: (yes|no)\r?$', | 
 |     input_api.re.IGNORECASE | input_api.re.MULTILINE) | 
 |   license_pattern = input_api.re.compile( | 
 |     r'^License: (.+)\r?$', | 
 |     input_api.re.IGNORECASE | input_api.re.MULTILINE) | 
 |   license_android_compatible_pattern = input_api.re.compile( | 
 |     r'^License Android Compatible: (yes|no)\r?$', | 
 |     input_api.re.IGNORECASE | input_api.re.MULTILINE) | 
 |  | 
 |   for f in readmes: | 
 |     if 'D' in f.Action(): | 
 |       _IgnoreIfDeleting(input_api, output_api, f, errors) | 
 |       continue | 
 |  | 
 |     contents = input_api.ReadFile(f) | 
 |     if (not shortname_pattern.search(contents) | 
 |         and not name_pattern.search(contents)): | 
 |       errors.append(output_api.PresubmitError( | 
 |         'Third party README files should contain either a \'Short Name\' or\n' | 
 |         'a \'Name\' which is the name under which the package is\n' | 
 |         'distributed. Check README.chromium.template for details.', | 
 |         [f])) | 
 |     if not version_pattern.search(contents): | 
 |       errors.append(output_api.PresubmitError( | 
 |         'Third party README files should contain a \'Version\' field.\n' | 
 |         'If the package is not versioned or the version is not known\n' | 
 |         'list the version as \'unknown\'.\n' | 
 |         'Check README.chromium.template for details.', | 
 |         [f])) | 
 |     if not release_pattern.search(contents): | 
 |       errors.append(output_api.PresubmitError( | 
 |         'Third party README files should contain a \'Security Critical\'\n' | 
 |         'field. This field specifies whether the package is built with\n' | 
 |         'Chromium. Check README.chromium.template for details.', | 
 |         [f])) | 
 |     license_match = license_pattern.search(contents) | 
 |     if not license_match: | 
 |       errors.append(output_api.PresubmitError( | 
 |         'Third party README files should contain a \'License\' field.\n' | 
 |         'This field specifies the license used by the package. Check\n' | 
 |         'README.chromium.template for details.', | 
 |         [f])) | 
 |     elif not LicenseIsCompatibleWithAndroid(input_api, license_match.group(1)) \ | 
 |          and not license_android_compatible_pattern.search(contents): | 
 |       errors.append(output_api.PresubmitPromptWarning( | 
 |         'Cannot determine whether specified license is compatible with\n' + | 
 |         'the Android licensing requirements. Please check that the license\n' + | 
 |         'name is spelled according to third_party/PRESUBMIT.py. Please see\n' + | 
 |         'README.chromium.template for details.', | 
 |         [f])) | 
 |   return errors | 
 |  | 
 |  | 
 | def _IgnoreIfDeleting(input_api, output_api, affected_file, errors): | 
 |   third_party_dir = input_api.os_path.dirname(affected_file.LocalPath()) | 
 |   for f in input_api.AffectedFiles(): | 
 |     if f.LocalPath().startswith(third_party_dir): | 
 |       if 'D' not in f.Action(): | 
 |         errors.append(output_api.PresubmitError( | 
 |           'Third party README should only be removed when the whole\n' | 
 |           'directory is being removed.\n', [f, affected_file])) | 
 |  | 
 |  | 
 | def CheckChangeOnUpload(input_api, output_api): | 
 |   results = [] | 
 |   results.extend(_CheckThirdPartyReadmesUpdated(input_api, output_api)) | 
 |   return results |