1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)"""Updates ExtensionFunctions enum in histograms.xml file with values read from 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)extension_function_histogram_value.h. 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)If the file was pretty-printed, the updated version is pretty-printed too. 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)""" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import logging 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import re 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import sys 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from xml.dom import minidom 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from diffutil import PromptUserToAcceptDiff 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from pretty_print import PrettyPrintNode 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)HISTOGRAMS_PATH = 'histograms.xml' 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ENUM_NAME = 'ExtensionFunctions' 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH = \ 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) '../../../chrome/browser/extensions/extension_function_histogram_value.h' 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ENUM_START_MARKER = "^enum HistogramValue {" 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ENUM_END_MARKER = "^ENUM_BOUNDARY" 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class UserError(Exception): 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) def __init__(self, message): 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Exception.__init__(self, message) 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) @property 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) def message(self): 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return self.args[0] 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def ExtractRegexGroup(line, regex): 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) m = re.match(regex, line) 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if m: 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return m.group(1) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else: 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return None 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def ReadHistogramValues(filename): 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) """Returns a list of pairs (label, value) corresponding to HistogramValue. 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Reads the extension_functions_histogram_value.h file, locates the 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) HistogramValue enum definition and returns a pair for each entry. 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) """ 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # Read the file as a list of lines 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) with open(filename) as f: 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content = f.readlines() 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # Locate the enum definition and collect all entries in it 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inside_enum = False # We haven't found the enum definition yet 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result = [] 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for line in content: 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) line = line.strip() 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if inside_enum: 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # Exit condition: we reached last enum value 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if re.match(ENUM_END_MARKER, line): 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inside_enum = False 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else: 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # Inside enum: generate new xml entry 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) label = ExtractRegexGroup(line.strip(), "^([\w]+)") 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if label: 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.append((label, enum_value)) 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) enum_value += 1 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else: 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if re.match(ENUM_START_MARKER, line): 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) inside_enum = True 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) enum_value = 0 # Start at 'UNKNOWN' 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def UpdateHistogramDefinitions(histogram_values, document): 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) """Sets the children of <enum name="ExtensionFunctions" ...> node in 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) |document| to values generated from policy ids contained in 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) |policy_templates|. 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Args: 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) histogram_values: A list of pairs (label, value) defining each extension 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) function 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) document: A minidom.Document object representing parsed histogram 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) definitions XML file. 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) """ 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # Find ExtensionFunctions enum. 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for enum_node in document.getElementsByTagName('enum'): 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if enum_node.attributes['name'].value == ENUM_NAME: 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_functions_enum_node = enum_node 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else: 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) raise UserError('No policy enum node found') 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # Remove existing values. 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) while extension_functions_enum_node.hasChildNodes(): 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_functions_enum_node.removeChild( 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_functions_enum_node.lastChild) 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # Add a "Generated from (...)" comment 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) comment = ' Generated from {0} '.format( 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH) 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_functions_enum_node.appendChild(document.createComment(comment)) 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # Add values generated from policy templates. 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (label, value) in histogram_values: 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) node = document.createElement('int') 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) node.attributes['value'] = str(value) 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) node.attributes['label'] = label 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_functions_enum_node.appendChild(node) 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def Log(message): 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) logging.info(message) 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def main(): 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if len(sys.argv) > 1: 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) print >>sys.stderr, 'No arguments expected!' 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sys.stderr.write(__doc__) 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sys.exit(1) 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Log('Reading histogram enum definition from "%s".' 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) % (EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH)) 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) histogram_values = ReadHistogramValues( 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH) 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Log('Reading existing histograms from "%s".' % (HISTOGRAMS_PATH)) 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) with open(HISTOGRAMS_PATH, 'rb') as f: 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) histograms_doc = minidom.parse(f) 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) f.seek(0) 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) xml = f.read() 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Log('Comparing histograms enum with new enum definition.') 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UpdateHistogramDefinitions(histogram_values, histograms_doc) 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Log('Writing out new histograms file.') 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new_xml = PrettyPrintNode(histograms_doc) 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if PromptUserToAcceptDiff(xml, new_xml, 'Is the updated version acceptable?'): 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) with open(HISTOGRAMS_PATH, 'wb') as f: 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) f.write(new_xml) 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Log('Done.') 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)if __name__ == '__main__': 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) main() 149