Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: components/policy/tools/generate_policy_source.py

Issue 838263005: Revert Revert "Expose chrome policies using Android's App Restrictions Schema" (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Actual change that should fix the issue Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/policy/BUILD.gn ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 '''python %prog [options] platform chromium_os_flag template 6 '''python %prog [options] platform chromium_os_flag template
7 7
8 platform specifies which platform source is being generated for 8 platform specifies which platform source is being generated for
9 and can be one of (win, mac, linux) 9 and can be one of (win, mac, linux)
10 chromium_os_flag should be 1 if this is a Chromium OS build 10 chromium_os_flag should be 1 if this is a Chromium OS build
11 template is the path to a .json policy template file.''' 11 template is the path to a .json policy template file.'''
12 12
13 from __future__ import with_statement 13 from __future__ import with_statement
14 from functools import partial 14 from functools import partial
15 import json 15 import json
16 from optparse import OptionParser 16 from optparse import OptionParser
17 import re 17 import re
18 import sys 18 import sys
19 import textwrap 19 import textwrap
20 import types 20 import types
21 from xml.sax.saxutils import escape as xml_escape
21 22
22 23
23 CHROME_POLICY_KEY = 'SOFTWARE\\\\Policies\\\\Google\\\\Chrome' 24 CHROME_POLICY_KEY = 'SOFTWARE\\\\Policies\\\\Google\\\\Chrome'
24 CHROMIUM_POLICY_KEY = 'SOFTWARE\\\\Policies\\\\Chromium' 25 CHROMIUM_POLICY_KEY = 'SOFTWARE\\\\Policies\\\\Chromium'
25 26
26 27
27 class PolicyDetails: 28 class PolicyDetails:
28 """Parses a policy template and caches all its details.""" 29 """Parses a policy template and caches all its details."""
29 30
30 # Maps policy types to a tuple with 3 other types: 31 # Maps policy types to a tuple with 5 other types:
31 # - the equivalent base::Value::Type or 'TYPE_EXTERNAL' if the policy 32 # - the equivalent base::Value::Type or 'TYPE_EXTERNAL' if the policy
32 # references external data 33 # references external data
33 # - the equivalent Protobuf field type 34 # - the equivalent Protobuf field type
34 # - the name of one of the protobufs for shared policy types 35 # - the name of one of the protobufs for shared policy types
36 # - the equivalent type in Android's App Restriction Schema
37 # - whether the equivalent app restriction type needs supporting resources
35 # TODO(joaodasilva): refactor the 'dict' type into a more generic 'json' type 38 # TODO(joaodasilva): refactor the 'dict' type into a more generic 'json' type
36 # that can also be used to represent lists of other JSON objects. 39 # that can also be used to represent lists of other JSON objects.
37 TYPE_MAP = { 40 TYPE_MAP = {
38 'dict': ('TYPE_DICTIONARY', 'string', 'String'), 41 'dict': ('TYPE_DICTIONARY', 'string', 'String',
39 'external': ('TYPE_EXTERNAL', 'string', 'String'), 42 'string', False),
40 'int': ('TYPE_INTEGER', 'int64', 'Integer'), 43 'external': ('TYPE_EXTERNAL', 'string', 'String',
41 'int-enum': ('TYPE_INTEGER', 'int64', 'Integer'), 44 'invalid', False),
42 'list': ('TYPE_LIST', 'StringList', 'StringList'), 45 'int': ('TYPE_INTEGER', 'int64', 'Integer',
43 'main': ('TYPE_BOOLEAN', 'bool', 'Boolean'), 46 'integer', False),
44 'string': ('TYPE_STRING', 'string', 'String'), 47 'int-enum': ('TYPE_INTEGER', 'int64', 'Integer',
45 'string-enum': ('TYPE_STRING', 'string', 'String'), 48 'choice', True),
46 'string-enum-list': ('TYPE_LIST', 'StringList', 'StringList'), 49 'list': ('TYPE_LIST', 'StringList', 'StringList',
50 'string', False),
51 'main': ('TYPE_BOOLEAN', 'bool', 'Boolean',
52 'bool', False),
53 'string': ('TYPE_STRING', 'string', 'String',
54 'string', False),
55 'string-enum': ('TYPE_STRING', 'string', 'String',
56 'choice', True),
57 'string-enum-list': ('TYPE_LIST', 'StringList', 'StringList',
58 'multi-select', True),
47 } 59 }
48 60
49 class EnumItem: 61 class EnumItem:
50 def __init__(self, item): 62 def __init__(self, item):
51 self.caption = PolicyDetails._RemovePlaceholders(item['caption']) 63 self.caption = PolicyDetails._RemovePlaceholders(item['caption'])
52 self.value = item['value'] 64 self.value = item['value']
53 65
54 def __init__(self, policy, os, is_chromium_os): 66 def __init__(self, policy, os, is_chromium_os):
55 self.id = policy['id'] 67 self.id = policy['id']
56 self.name = policy['name'] 68 self.name = policy['name']
(...skipping 21 matching lines...) Expand all
78 self.platforms.append(platform_sub) 90 self.platforms.append(platform_sub)
79 else: 91 else:
80 self.platforms.append(platform) 92 self.platforms.append(platform)
81 93
82 self.platforms.sort() 94 self.platforms.sort()
83 self.is_supported = expected_platform in self.platforms 95 self.is_supported = expected_platform in self.platforms
84 96
85 if not PolicyDetails.TYPE_MAP.has_key(policy['type']): 97 if not PolicyDetails.TYPE_MAP.has_key(policy['type']):
86 raise NotImplementedError('Unknown policy type for %s: %s' % 98 raise NotImplementedError('Unknown policy type for %s: %s' %
87 (policy['name'], policy['type'])) 99 (policy['name'], policy['type']))
88 self.policy_type, self.protobuf_type, self.policy_protobuf_type = \ 100 self.policy_type, self.protobuf_type, self.policy_protobuf_type, \
89 PolicyDetails.TYPE_MAP[policy['type']] 101 self.restriction_type, self.has_restriction_resources = \
102 PolicyDetails.TYPE_MAP[policy['type']]
90 self.schema = policy['schema'] 103 self.schema = policy['schema']
91 104
92 self.desc = '\n'.join( 105 self.desc = '\n'.join(
93 map(str.strip, 106 map(str.strip,
94 PolicyDetails._RemovePlaceholders(policy['desc']).splitlines())) 107 PolicyDetails._RemovePlaceholders(policy['desc']).splitlines()))
95 self.caption = PolicyDetails._RemovePlaceholders(policy['caption']) 108 self.caption = PolicyDetails._RemovePlaceholders(policy['caption'])
96 self.max_size = policy.get('max_size', 0) 109 self.max_size = policy.get('max_size', 0)
97 110
98 items = policy.get('items') 111 items = policy.get('items')
99 if items is None: 112 if items is None:
(...skipping 29 matching lines...) Expand all
129 help='generate cloud policy protobuf file', 142 help='generate cloud policy protobuf file',
130 metavar='FILE') 143 metavar='FILE')
131 parser.add_option('--csp', '--chrome-settings-protobuf', 144 parser.add_option('--csp', '--chrome-settings-protobuf',
132 dest='chrome_settings_proto_path', 145 dest='chrome_settings_proto_path',
133 help='generate chrome settings protobuf file', 146 help='generate chrome settings protobuf file',
134 metavar='FILE') 147 metavar='FILE')
135 parser.add_option('--cpd', '--cloud-policy-decoder', 148 parser.add_option('--cpd', '--cloud-policy-decoder',
136 dest='cloud_policy_decoder_path', 149 dest='cloud_policy_decoder_path',
137 help='generate C++ code decoding the cloud policy protobuf', 150 help='generate C++ code decoding the cloud policy protobuf',
138 metavar='FILE') 151 metavar='FILE')
152 parser.add_option('--ard', '--app-restrictions-definition',
153 dest='app_restrictions_path',
154 help='generate an XML file as specified by '
155 'Android\'s App Restriction Schema',
156 metavar='FILE')
157 parser.add_option('--arr', '--app-restrictions-resources',
158 dest='app_resources_path',
159 help='generate an XML file with resources supporting the '
160 'restrictions defined in --app-restrictions-definition '
161 'parameter',
162 metavar='FILE')
139 163
140 (opts, args) = parser.parse_args() 164 (opts, args) = parser.parse_args()
141 165
142 if len(args) != 3: 166 if len(args) != 3:
143 print 'exactly platform, chromium_os flag and input file must be specified.' 167 print 'exactly platform, chromium_os flag and input file must be specified.'
144 parser.print_help() 168 parser.print_help()
145 return 2 169 return 2
146 170
147 os = args[0] 171 os = args[0]
148 is_chromium_os = args[1] == '1' 172 is_chromium_os = args[1] == '1'
149 template_file_name = args[2] 173 template_file_name = args[2]
150 174
151 template_file_contents = _LoadJSONFile(template_file_name) 175 template_file_contents = _LoadJSONFile(template_file_name)
152 policy_details = [ PolicyDetails(policy, os, is_chromium_os) 176 policy_details = [ PolicyDetails(policy, os, is_chromium_os)
153 for policy in _Flatten(template_file_contents) ] 177 for policy in _Flatten(template_file_contents) ]
154 sorted_policy_details = sorted(policy_details, key=lambda policy: policy.name) 178 sorted_policy_details = sorted(policy_details, key=lambda policy: policy.name)
155 179
156 def GenerateFile(path, writer, sorted=False): 180 def GenerateFile(path, writer, sorted=False, xml=False):
157 if path: 181 if path:
158 with open(path, 'w') as f: 182 with open(path, 'w') as f:
159 _OutputGeneratedWarningHeader(f, template_file_name) 183 _OutputGeneratedWarningHeader(f, template_file_name, xml)
160 writer(sorted and sorted_policy_details or policy_details, os, f) 184 writer(sorted and sorted_policy_details or policy_details, os, f)
161 185
162 GenerateFile(opts.header_path, _WritePolicyConstantHeader, sorted=True) 186 GenerateFile(opts.header_path, _WritePolicyConstantHeader, sorted=True)
163 GenerateFile(opts.source_path, _WritePolicyConstantSource, sorted=True) 187 GenerateFile(opts.source_path, _WritePolicyConstantSource, sorted=True)
164 GenerateFile(opts.cloud_policy_proto_path, _WriteCloudPolicyProtobuf) 188 GenerateFile(opts.cloud_policy_proto_path, _WriteCloudPolicyProtobuf)
165 GenerateFile(opts.chrome_settings_proto_path, _WriteChromeSettingsProtobuf) 189 GenerateFile(opts.chrome_settings_proto_path, _WriteChromeSettingsProtobuf)
166 GenerateFile(opts.cloud_policy_decoder_path, _WriteCloudPolicyDecoder) 190 GenerateFile(opts.cloud_policy_decoder_path, _WriteCloudPolicyDecoder)
167 191
192 if os == 'android':
193 GenerateFile(opts.app_restrictions_path, _WriteAppRestrictions, xml=True)
194 GenerateFile(opts.app_resources_path, _WriteResourcesForPolicies, xml=True)
195
168 return 0 196 return 0
169 197
170 198
171 #------------------ shared helpers ---------------------------------# 199 #------------------ shared helpers ---------------------------------#
172 200
173 def _OutputGeneratedWarningHeader(f, template_file_path): 201 def _OutputGeneratedWarningHeader(f, template_file_path, xml_style):
174 f.write('//\n' 202 left_margin = '//'
175 '// DO NOT MODIFY THIS FILE DIRECTLY!\n' 203 if xml_style:
176 '// IT IS GENERATED BY generate_policy_source.py\n' 204 left_margin = ' '
177 '// FROM ' + template_file_path + '\n' 205 f.write('<?xml version="1.0" encoding="utf-8"?>\n'
178 '//\n\n') 206 '<!--\n')
207 else:
208 f.write('//\n')
209
210 f.write(left_margin + ' DO NOT MODIFY THIS FILE DIRECTLY!\n')
211 f.write(left_margin + ' IT IS GENERATED BY generate_policy_source.py\n')
212 f.write(left_margin + ' FROM ' + template_file_path + '\n')
213
214 if xml_style:
215 f.write('-->\n\n')
216 else:
217 f.write(left_margin + '\n\n')
179 218
180 219
181 COMMENT_WRAPPER = textwrap.TextWrapper() 220 COMMENT_WRAPPER = textwrap.TextWrapper()
182 COMMENT_WRAPPER.width = 80 221 COMMENT_WRAPPER.width = 80
183 COMMENT_WRAPPER.initial_indent = '// ' 222 COMMENT_WRAPPER.initial_indent = '// '
184 COMMENT_WRAPPER.subsequent_indent = '// ' 223 COMMENT_WRAPPER.subsequent_indent = '// '
185 COMMENT_WRAPPER.replace_whitespace = False 224 COMMENT_WRAPPER.replace_whitespace = False
186 225
187 226
188 # Writes a comment, each line prefixed by // and wrapped to 80 spaces. 227 # Writes a comment, each line prefixed by // and wrapped to 80 spaces.
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 f.write('};\n\n') 593 f.write('};\n\n')
555 594
556 def GetByID(self, id_str): 595 def GetByID(self, id_str):
557 if not isinstance(id_str, types.StringTypes): 596 if not isinstance(id_str, types.StringTypes):
558 return id_str 597 return id_str
559 if not self.id_map.has_key(id_str): 598 if not self.id_map.has_key(id_str):
560 raise RuntimeError('Invalid $ref: ' + id_str) 599 raise RuntimeError('Invalid $ref: ' + id_str)
561 return self.id_map[id_str] 600 return self.id_map[id_str]
562 601
563 def ResolveID(self, index, params): 602 def ResolveID(self, index, params):
564 return params[:index] + (self.GetByID(params[index]),) + params[index+1:] 603 return params[:index] + (self.GetByID(params[index]),) + params[index + 1:]
565 604
566 def ResolveReferences(self): 605 def ResolveReferences(self):
567 """Resolve reference mapping, required to be called after Generate() 606 """Resolve reference mapping, required to be called after Generate()
568 607
569 After calling Generate(), the type of indices used in schema structures 608 After calling Generate(), the type of indices used in schema structures
570 might be either int or string. An int type suggests that it's a resolved 609 might be either int or string. An int type suggests that it's a resolved
571 index, but for string type it's unresolved. Resolving a reference is as 610 index, but for string type it's unresolved. Resolving a reference is as
572 simple as looking up for corresponding ID in self.id_map, and replace the 611 simple as looking up for corresponding ID in self.id_map, and replace the
573 old index with the mapped index. 612 old index with the mapped index.
574 """ 613 """
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 1000
962 1001
963 def _WriteCloudPolicyDecoder(policies, os, f): 1002 def _WriteCloudPolicyDecoder(policies, os, f):
964 f.write(CPP_HEAD) 1003 f.write(CPP_HEAD)
965 for policy in policies: 1004 for policy in policies:
966 if policy.is_supported and not policy.is_device_only: 1005 if policy.is_supported and not policy.is_device_only:
967 _WritePolicyCode(f, policy) 1006 _WritePolicyCode(f, policy)
968 f.write(CPP_FOOT) 1007 f.write(CPP_FOOT)
969 1008
970 1009
1010 def _EscapeResourceString(raw_resource):
1011 if type(raw_resource) == int:
1012 return raw_resource
1013 return xml_escape(raw_resource)\
1014 .replace('\\', '\\\\')\
1015 .replace('\"','\\\"')\
1016 .replace('\'','\\\'')
1017
1018 def _WriteAppRestrictions(policies, os, f):
1019
1020 def WriteRestrictionCommon(key):
1021 f.write(' <restriction\n'
1022 ' android:key="%s"\n' % key)
1023 f.write(' android:title="@string/%sTitle"\n' % key)
1024 f.write(' android:description="@string/%sDesc"\n' % key)
1025
1026 def WriteItemsDefinition(key):
1027 f.write(' android:entries="@array/%sEntries"\n' % key)
1028 f.write(' android:entryValues="@array/%sValues"\n' % key)
1029
1030 def WriteAppRestriction(policy):
1031 policy_name = policy.name
1032 WriteRestrictionCommon(policy_name)
1033
1034 if policy.has_restriction_resources:
1035 WriteItemsDefinition(policy_name)
1036
1037 f.write(' android:restrictionType="%s"/>' % policy.restriction_type)
1038 f.write('\n\n')
1039
1040 # _WriteAppRestrictions body
1041 f.write('<restrictions xmlns:android="'
1042 'http://schemas.android.com/apk/res/android">\n\n')
1043 for policy in policies:
1044 if policy.is_supported and policy.restriction_type != 'invalid':
1045 WriteAppRestriction(policy)
1046 f.write('</restrictions>')
1047
1048
1049 def _WriteResourcesForPolicies(policies, os, f):
1050
1051 # TODO(knn): Update this to support i18n.
1052 def WriteString(key, value):
1053 f.write(' <string name="%s">%s</string>\n'
1054 % (key, _EscapeResourceString(value)))
1055
1056 def WriteItems(key, items):
1057 if items:
1058 f.write(' <string-array name="%sEntries">\n' % key)
1059 for item in items:
1060 f.write(' <item>%s</item>\n' %
1061 _EscapeResourceString(item.caption))
1062 f.write(' </string-array>\n')
1063 f.write(' <string-array name="%sValues">\n' % key)
1064 for item in items:
1065 f.write(' <item>%s</item>\n' % _EscapeResourceString(item.value))
1066 f.write(' </string-array>\n')
1067
1068 def WriteResourceForPolicy(policy):
1069 policy_name = policy.name
1070 WriteString(policy_name + 'Title', policy.caption)
1071
1072 # Get the first line of the policy description.
1073 description = policy.desc.split('\n', 1)[0]
1074 WriteString(policy_name + 'Desc', description)
1075
1076 if policy.has_restriction_resources:
1077 WriteItems(policy_name, policy.items)
1078
1079 # _WriteResourcesForPolicies body
1080 f.write('<resources>\n\n')
1081 for policy in policies:
1082 if policy.is_supported and policy.restriction_type != 'invalid':
1083 WriteResourceForPolicy(policy)
1084 f.write('</resources>')
1085
1086
971 if __name__ == '__main__': 1087 if __name__ == '__main__':
972 sys.exit(main()) 1088 sys.exit(main())
OLDNEW
« no previous file with comments | « components/policy/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698