- add sources.
[platform/framework/web/crosswalk.git] / src / tools / metrics / histograms / update_policies.py
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.
4
5 """Updates EnterprisePolicies enum in histograms.xml file with policy
6 definitions read from policy_templates.json.
7
8 If the file was pretty-printed, the updated version is pretty-printed too.
9 """
10
11 import re
12 import sys
13
14 from ast import literal_eval
15 from optparse import OptionParser
16 from xml.dom import minidom
17
18 from diffutil import PromptUserToAcceptDiff
19 from pretty_print import PrettyPrintNode
20
21 HISTOGRAMS_PATH = 'histograms.xml'
22 POLICY_TEMPLATES_PATH = '../../../chrome/app/policy/policy_templates.json'
23 ENUM_NAME = 'EnterprisePolicies'
24
25 class UserError(Exception):
26   def __init__(self, message):
27     Exception.__init__(self, message)
28
29   @property
30   def message(self):
31     return self.args[0]
32
33
34 def FlattenPolicies(policy_definitions, policy_list):
35   """Appends a list of policies defined in |policy_definitions| to
36   |policy_list|, flattening subgroups.
37
38   Args:
39     policy_definitions: A list of policy definitions and groups, as in
40                         policy_templates.json file.
41     policy_list: A list that has policy definitions appended to it.
42   """
43   for policy in policy_definitions:
44     if policy['type'] == 'group':
45       FlattenPolicies(policy['policies'], policy_list)
46     else:
47       policy_list.append(policy)
48
49
50 def ParsePlaceholders(text):
51   """Parse placeholders in |text|, making it more human-readable. The format of
52   |text| is exactly the same as in captions in policy_templates.json: it can
53   contain XML tags (ph, ex) and $1-like substitutions. Note that this function
54   does only a very simple parsing that is not fully correct, but should be
55   enough for all practical situations.
56
57   Args:
58     text: A string containing placeholders.
59
60   Returns:
61     |text| with placeholders removed or replaced by readable text.
62   """
63   text = re.sub(r'\$\d+', '', text)    # Remove $1-like substitutions.
64   text = re.sub(r'<[^>]+>', '', text)  # Remove XML tags.
65   return text
66
67
68 def UpdateHistogramDefinitions(policy_templates, doc):
69   """Sets the children of <enum name="EnterprisePolicies" ...> node in |doc| to
70   values generated from policy ids contained in |policy_templates|.
71
72   Args:
73     policy_templates: A list of dictionaries, defining policies or policy
74                       groups. The format is exactly the same as in
75                       policy_templates.json file.
76     doc: A minidom.Document object representing parsed histogram definitions
77          XML file.
78   """
79   # Find EnterprisePolicies enum.
80   for enum_node in doc.getElementsByTagName('enum'):
81     if enum_node.attributes['name'].value == ENUM_NAME:
82         policy_enum_node = enum_node
83         break
84   else:
85     raise UserError('No policy enum node found')
86
87   # Remove existing values.
88   while policy_enum_node.hasChildNodes():
89     policy_enum_node.removeChild(policy_enum_node.lastChild)
90
91   # Add a "Generated from (...)" comment
92   comment = ' Generated from {0} '.format(POLICY_TEMPLATES_PATH)
93   policy_enum_node.appendChild(doc.createComment(comment))
94
95   # Add values generated from policy templates.
96   ordered_policies = []
97   FlattenPolicies(policy_templates['policy_definitions'], ordered_policies)
98   ordered_policies.sort(key=lambda policy: policy['id'])
99   for policy in ordered_policies:
100     node = doc.createElement('int')
101     node.attributes['value'] = str(policy['id'])
102     node.attributes['label'] = ParsePlaceholders(policy['caption'])
103     policy_enum_node.appendChild(node)
104
105
106 def main():
107   if len(sys.argv) > 1:
108     print >>sys.stderr, 'No arguments expected!'
109     sys.stderr.write(__doc__)
110     sys.exit(1)
111
112   with open(POLICY_TEMPLATES_PATH, 'rb') as f:
113     policy_templates = literal_eval(f.read())
114   with open(HISTOGRAMS_PATH, 'rb') as f:
115     histograms_doc = minidom.parse(f)
116     f.seek(0)
117     xml = f.read()
118
119   UpdateHistogramDefinitions(policy_templates, histograms_doc)
120
121   new_xml = PrettyPrintNode(histograms_doc)
122   if PromptUserToAcceptDiff(xml, new_xml, 'Is the updated version acceptable?'):
123     with open(HISTOGRAMS_PATH, 'wb') as f:
124       f.write(new_xml)
125
126
127 if __name__ == '__main__':
128   try:
129     main()
130   except UserError as e:
131     print >>sys.stderr, e.message
132     sys.exit(1)