1 # Copyright 2013 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 """Updates ExtensionFunctions enum in histograms.xml file with values read from
6 extension_function_histogram_value.h.
8 If the file was pretty-printed, the updated version is pretty-printed too.
15 from xml
.dom
import minidom
17 from diffutil
import PromptUserToAcceptDiff
18 from pretty_print
import PrettyPrintNode
20 HISTOGRAMS_PATH
= 'histograms.xml'
21 ENUM_NAME
= 'ExtensionFunctions'
23 EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH
= \
24 '../../../chrome/browser/extensions/extension_function_histogram_value.h'
25 ENUM_START_MARKER
= "^enum HistogramValue {"
26 ENUM_END_MARKER
= "^ENUM_BOUNDARY"
29 class UserError(Exception):
30 def __init__(self
, message
):
31 Exception.__init
__(self
, message
)
37 def ExtractRegexGroup(line
, regex
):
38 m
= re
.match(regex
, line
)
45 def ReadHistogramValues(filename
):
46 """Returns a list of pairs (label, value) corresponding to HistogramValue.
48 Reads the extension_functions_histogram_value.h file, locates the
49 HistogramValue enum definition and returns a pair for each entry.
52 # Read the file as a list of lines
53 with
open(filename
) as f
:
54 content
= f
.readlines()
56 # Locate the enum definition and collect all entries in it
57 inside_enum
= False # We haven't found the enum definition yet
62 # Exit condition: we reached last enum value
63 if re
.match(ENUM_END_MARKER
, line
):
66 # Inside enum: generate new xml entry
67 label
= ExtractRegexGroup(line
.strip(), "^([\w]+)")
69 result
.append((label
, enum_value
))
72 if re
.match(ENUM_START_MARKER
, line
):
74 enum_value
= 0 # Start at 'UNKNOWN'
78 def UpdateHistogramDefinitions(histogram_values
, document
):
79 """Sets the children of <enum name="ExtensionFunctions" ...> node in
80 |document| to values generated from policy ids contained in
84 histogram_values: A list of pairs (label, value) defining each extension
86 document: A minidom.Document object representing parsed histogram
90 # Find ExtensionFunctions enum.
91 for enum_node
in document
.getElementsByTagName('enum'):
92 if enum_node
.attributes
['name'].value
== ENUM_NAME
:
93 extension_functions_enum_node
= enum_node
96 raise UserError('No policy enum node found')
98 # Remove existing values.
99 while extension_functions_enum_node
.hasChildNodes():
100 extension_functions_enum_node
.removeChild(
101 extension_functions_enum_node
.lastChild
)
103 # Add a "Generated from (...)" comment
104 comment
= ' Generated from {0} '.format(
105 EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH
)
106 extension_functions_enum_node
.appendChild(document
.createComment(comment
))
108 # Add values generated from policy templates.
109 for (label
, value
) in histogram_values
:
110 node
= document
.createElement('int')
111 node
.attributes
['value'] = str(value
)
112 node
.attributes
['label'] = label
113 extension_functions_enum_node
.appendChild(node
)
116 logging
.info(message
)
119 if len(sys
.argv
) > 1:
120 print >>sys
.stderr
, 'No arguments expected!'
121 sys
.stderr
.write(__doc__
)
124 Log('Reading histogram enum definition from "%s".'
125 % (EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH
))
126 histogram_values
= ReadHistogramValues(
127 EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH
)
129 Log('Reading existing histograms from "%s".' % (HISTOGRAMS_PATH
))
130 with
open(HISTOGRAMS_PATH
, 'rb') as f
:
131 histograms_doc
= minidom
.parse(f
)
135 Log('Comparing histograms enum with new enum definition.')
136 UpdateHistogramDefinitions(histogram_values
, histograms_doc
)
138 Log('Writing out new histograms file.')
139 new_xml
= PrettyPrintNode(histograms_doc
)
140 if PromptUserToAcceptDiff(xml
, new_xml
, 'Is the updated version acceptable?'):
141 with
open(HISTOGRAMS_PATH
, 'wb') as f
:
147 if __name__
== '__main__':