1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """Presubmit script for HTML files in chrome/browser/resources.
7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
8 for more details about the presubmit API built into depot_tools.
11 ACTION_XML_PATH
= '../../../tools/metrics/actions/actions.xml'
13 def CheckUserActionUpdate(input_api
, output_api
, action_xml_path
):
14 """Checks if any new user action has been added."""
15 if any('actions.xml' == input_api
.os_path
.basename(f
) for f
in
16 input_api
.change
.LocalPaths()):
17 # If actions.xml is already included in the changelist, the PRESUBMIT
18 # for actions.xml will do a more complete presubmit check.
21 file_filter
= lambda f
: f
.LocalPath().endswith('.html')
22 action_re
= r
'(^|\s+)metric\s*=\s*"([^ ]*)"'
23 current_actions
= None
24 for f
in input_api
.AffectedFiles(file_filter
=file_filter
):
25 for line_num
, line
in f
.ChangedContents():
26 match
= input_api
.re
.search(action_re
, line
)
28 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
30 if not current_actions
:
31 with
open(action_xml_path
) as actions_f
:
32 current_actions
= actions_f
.read()
34 metric_name
= match
.group(2)
35 is_boolean
= IsBoolean(f
.NewContents(), metric_name
, input_api
)
37 # Search for the matched user action name in |current_actions|.
38 if not IsActionPresent(current_actions
, metric_name
, is_boolean
):
39 return [output_api
.PresubmitPromptWarning(
40 'File %s line %d: %s is missing in '
41 'tools/metrics/actions/actions.xml. Please run '
42 'tools/metrics/actions/extract_actions.py to update.'
43 % (f
.LocalPath(), line_num
, metric_name
), [])]
47 def IsActionPresent(current_actions
, metric_name
, is_boolean
):
48 """Checks if metric_name is defined in the actions file.
50 Checks whether there's matching entries in an actions.xml file for the given
51 |metric_name|, depending on whether it is a boolean action.
54 current_actions: The content of the actions.xml file.
55 metric_name: The name for which the check should be done.
56 is_boolean: Whether the action comes from a boolean control.
59 action
= 'name="{0}"'.format(metric_name
)
60 return action
in current_actions
62 action_disabled
= 'name="{0}_Disable"'.format(metric_name
)
63 action_enabled
= 'name="{0}_Enable"'.format(metric_name
)
65 return (action_disabled
in current_actions
and
66 action_enabled
in current_actions
)
69 def IsBoolean(new_content_lines
, metric_name
, input_api
):
70 """Check whether action defined in the changed code is boolean or not.
72 Checks whether the action comes from boolean control based on the HTML
76 new_content_lines: List of changed lines.
77 metric_name: The name for which the check should be done.
79 new_content
= '\n'.join(new_content_lines
)
81 html_element_re
= r
'<(.*?)(^|\s+)metric\s*=\s*"%s"(.*?)>' % (metric_name
)
82 type_re
= (r
'datatype\s*=\s*"boolean"|type\s*=\s*"checkbox"|'
83 'type\s*=\s*"radio".*?value\s*=\s*("true"|"false")')
85 match
= input_api
.re
.search(html_element_re
, new_content
, input_api
.re
.DOTALL
)
87 any(input_api
.re
.search(type_re
, match
.group(i
)) for i
in (1, 3)))
90 def CheckChangeOnUpload(input_api
, output_api
):
91 return CheckUserActionUpdate(input_api
, output_api
, ACTION_XML_PATH
)
94 def CheckChangeOnCommit(input_api
, output_api
):
95 return CheckUserActionUpdate(input_api
, output_api
, ACTION_XML_PATH
)