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

Side by Side Diff: chrome/tools/build/generate_policy_source.py

Issue 31273002: Generate the Chrome policy schema at compile time. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: added comments Created 7 years, 2 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 | Annotate | Revision Log
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
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 class EnumItem: 46 class EnumItem:
47 def __init__(self, item): 47 def __init__(self, item):
48 self.caption = PolicyDetails._RemovePlaceholders(item['caption']) 48 self.caption = PolicyDetails._RemovePlaceholders(item['caption'])
49 self.value = item['value'] 49 self.value = item['value']
50 50
51 def __init__(self, policy, os, is_chromium_os): 51 def __init__(self, policy, os, is_chromium_os):
52 self.id = policy['id'] 52 self.id = policy['id']
53 self.name = policy['name'] 53 self.name = policy['name']
54 self.is_deprecated = policy.get('deprecated', False) 54 self.is_deprecated = policy.get('deprecated', False)
55 self.is_device_only = policy.get('device_only', False) 55 self.is_device_only = policy.get('device_only', False)
56 self.schema = policy.get('schema', {})
56 57
57 if is_chromium_os: 58 if is_chromium_os:
58 expected_platform = 'chrome_os' 59 expected_platform = 'chrome_os'
59 else: 60 else:
60 expected_platform = os.lower() 61 expected_platform = os.lower()
61 62
62 self.platforms = [] 63 self.platforms = []
63 for platform, version in [ p.split(':') for p in policy['supported_on'] ]: 64 for platform, version in [ p.split(':') for p in policy['supported_on'] ]:
64 if not version.endswith('-'): 65 if not version.endswith('-'):
65 continue 66 continue
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 210
210 def _WritePolicyConstantHeader(policies, os, f): 211 def _WritePolicyConstantHeader(policies, os, f):
211 f.write('#ifndef CHROME_COMMON_POLICY_CONSTANTS_H_\n' 212 f.write('#ifndef CHROME_COMMON_POLICY_CONSTANTS_H_\n'
212 '#define CHROME_COMMON_POLICY_CONSTANTS_H_\n' 213 '#define CHROME_COMMON_POLICY_CONSTANTS_H_\n'
213 '\n' 214 '\n'
214 '#include <string>\n' 215 '#include <string>\n'
215 '\n' 216 '\n'
216 '#include "base/basictypes.h"\n' 217 '#include "base/basictypes.h"\n'
217 '#include "base/values.h"\n' 218 '#include "base/values.h"\n'
218 '\n' 219 '\n'
219 'namespace policy {\n\n') 220 'namespace policy {\n'
221 '\n'
222 'namespace internal {\n'
223 'struct SchemaData;\n'
224 '}\n\n')
220 225
221 if os == 'win': 226 if os == 'win':
222 f.write('// The windows registry path where Chrome policy ' 227 f.write('// The windows registry path where Chrome policy '
223 'configuration resides.\n' 228 'configuration resides.\n'
224 'extern const wchar_t kRegistryChromePolicyKey[];\n') 229 'extern const wchar_t kRegistryChromePolicyKey[];\n')
225 230
226 f.write('// Lists metadata such as name, expected type and id for all\n' 231 f.write('// Lists metadata such as name, expected type and id for all\n'
227 '// policies. Used to initialize ConfigurationPolicyProviders and\n' 232 '// policies. Used to initialize ConfigurationPolicyProviders and\n'
228 '// CloudExternalDataManagers.\n' 233 '// CloudExternalDataManagers.\n'
229 'struct PolicyDefinitionList {\n' 234 'struct PolicyDefinitionList {\n'
230 ' struct Entry {\n' 235 ' struct Entry {\n'
231 ' const char* name;\n' 236 ' const char* name;\n'
232 ' base::Value::Type value_type;\n' 237 ' base::Value::Type value_type;\n'
233 ' bool device_policy;\n' 238 ' bool device_policy;\n'
234 ' int id;\n' 239 ' int id;\n'
235 ' size_t max_external_data_size;\n' 240 ' size_t max_external_data_size;\n'
236 ' };\n' 241 ' };\n'
237 '\n' 242 '\n'
238 ' const Entry* begin;\n' 243 ' const Entry* begin;\n'
239 ' const Entry* end;\n' 244 ' const Entry* end;\n'
240 '};\n' 245 '};\n'
241 '\n' 246 '\n'
242 '// Returns true if the given policy is deprecated.\n' 247 '// Returns true if the given policy is deprecated.\n'
243 'bool IsDeprecatedPolicy(const std::string& policy);\n' 248 'bool IsDeprecatedPolicy(const std::string& policy);\n'
244 '\n' 249 '\n'
245 '// Returns the default policy definition list for Chrome.\n' 250 '// Returns the default policy definition list for Chrome.\n'
246 'const PolicyDefinitionList* GetChromePolicyDefinitionList();\n\n') 251 'const PolicyDefinitionList* GetChromePolicyDefinitionList();\n'
252 '\n'
253 '// Returns the schema data of the Chrome policy schema.\n'
254 'const internal::SchemaData* GetChromeSchemaData();\n'
255 '\n')
247 f.write('// Key names for the policy settings.\n' 256 f.write('// Key names for the policy settings.\n'
248 'namespace key {\n\n') 257 'namespace key {\n\n')
249 for policy in policies: 258 for policy in policies:
250 # TODO(joaodasilva): Include only supported policies in 259 # TODO(joaodasilva): Include only supported policies in
251 # configuration_policy_handler.cc and configuration_policy_handler_list.cc 260 # configuration_policy_handler.cc and configuration_policy_handler_list.cc
252 # so that these names can be conditional on 'policy.is_supported'. 261 # so that these names can be conditional on 'policy.is_supported'.
253 # http://crbug.com/223616 262 # http://crbug.com/223616
254 f.write('extern const char k' + policy.name + '[];\n') 263 f.write('extern const char k' + policy.name + '[];\n')
255 f.write('\n} // namespace key\n\n' 264 f.write('\n} // namespace key\n\n'
256 '} // namespace policy\n\n' 265 '} // namespace policy\n\n'
257 '#endif // CHROME_COMMON_POLICY_CONSTANTS_H_\n') 266 '#endif // CHROME_COMMON_POLICY_CONSTANTS_H_\n')
258 267
259 268
260 #------------------ policy constants source ------------------------# 269 #------------------ policy constants source ------------------------#
261 270
262 def _GetValueType(policy_type): 271 def _GetValueType(policy_type):
263 return policy_type if policy_type != 'TYPE_EXTERNAL' else 'TYPE_DICTIONARY' 272 return policy_type if policy_type != 'TYPE_EXTERNAL' else 'TYPE_DICTIONARY'
264 273
265 274
275 # A mapping of the simple schema types to base::Value::Types.
276 SIMPLE_SCHEMA_NAME_MAP = {
277 'boolean': 'TYPE_BOOLEAN',
278 'integer': 'TYPE_INTEGER',
279 'null' : 'TYPE_NULL',
280 'number' : 'TYPE_DOUBLE',
281 'string' : 'TYPE_STRING',
282 }
283
284
285 class SchemaNodesGenerator:
286 """Builds the internal structs to represent a JSON schema."""
287
288 def __init__(self, shared_strings):
289 """Creates a new generator.
290
291 |shared_strings| is a map of strings to a C expression that evaluates to
292 that string at runtime. This mapping can be used to reuse existing string
293 constants."""
294 self.shared_strings = shared_strings
295 self.schema_nodes = []
296 self.property_nodes = []
297 self.properties_nodes = []
298 self.simple_types = {
299 'boolean': -1,
300 'integer': -1,
dconnelly 2013/10/22 11:55:52 use None instead of -1
Joao da Silva 2013/10/22 12:53:27 Done.
301 'null': -1,
302 'number': -1,
303 'string': -1,
304 }
305 self.stringlist_type = -1
306
307 def GetString(self, s):
308 if s in self.shared_strings:
309 return self.shared_strings[s]
310 else:
311 return '"%s"' % s
312
313 def AppendSchema(self, type, extra, comment=''):
314 index = len(self.schema_nodes)
315 self.schema_nodes.append((type, extra, comment))
316 return index
317
318 def GetSimpleType(self, name):
319 assert name in self.simple_types
320 assert name in SIMPLE_SCHEMA_NAME_MAP
321 if self.simple_types[name] == -1:
322 self.simple_types[name] = self.AppendSchema(
323 SIMPLE_SCHEMA_NAME_MAP[name],
324 -1,
325 'simple type: ' + name)
326 return self.simple_types[name]
327
328 def GetStringList(self):
329 if self.stringlist_type == -1:
330 self.stringlist_type = self.AppendSchema(
331 'TYPE_LIST',
332 self.GetSimpleType('string'),
333 'simple type: stringlist')
334 return self.stringlist_type
335
336 def Generate(self, schema, name):
337 """Generates the structs for the given schema.
338
339 |schema|: a valid JSON schema in a dictionary.
340 |name|: the name of the current node, for the generated comments."""
341 # Simple types use shared nodes.
342 if schema['type'] in self.simple_types:
343 return self.GetSimpleType(schema['type'])
344
345 if schema['type'] == 'array':
346 # Special case for lists of strings, which is a common policy type.
347 if schema['items']['type'] == 'string':
348 return self.GetStringList()
349 return self.AppendSchema(
350 'TYPE_LIST',
351 self.Generate(schema['items'], 'items of ' + name))
352 elif schema['type'] == 'object':
353 # Reserve an index first, so that dictionaries come before their
354 # properties. This makes sure that the root node is the first in the
355 # SchemaNodes array.
356 index = self.AppendSchema('TYPE_DICTIONARY', -1)
357
358 if 'additionalProperties' in schema:
359 additionalProperties = self.Generate(
360 schema['additionalProperties'],
361 'additionalProperties of ' + name)
362 else:
363 additionalProperties = -1
364
365 # Properties must be sorted by name, for the binary search lookup.
366 sorted_properties = sorted(schema.get('properties', {}).items())
367 properties = [ (self.GetString(key), self.Generate(schema, key))
dconnelly 2013/10/22 11:55:52 This can be a generator expression
Joao da Silva 2013/10/22 12:53:27 Done.
Joao da Silva 2013/11/03 20:55:00 Actually it can't :-) Turning this into a generat
dconnelly 2013/11/04 09:18:51 yuck, good catch On 2013/11/03 20:55:00, Joao da
368 for key, schema in sorted_properties ]
369 begin = len(self.property_nodes)
370 self.property_nodes += properties
371 end = len(self.property_nodes)
372
373 extra = len(self.properties_nodes)
374 self.properties_nodes.append((begin, end, additionalProperties, name))
375
376 # Set the right data at |index| now.
377 self.schema_nodes[index] = ('TYPE_DICTIONARY', extra, name)
378 return index
379 else:
380 assert False
381
382 def Write(self, f):
383 """Writes the generated structs to the given file.
384
385 |f| an open file to write to."""
386 f.write('const internal::SchemaNode kSchemas[] = {\n'
387 '// Type Extra\n')
388 for type, extra, comment in self.schema_nodes:
389 type += ','
390 f.write(' { base::Value::%-18s %3d }, // %s\n' % (type, extra, comment))
391 f.write('};\n\n')
392
393 f.write('const internal::PropertyNode kPropertyNodes[] = {\n'
394 '// Property #Schema\n')
395 for key, schema in self.property_nodes:
396 key += ','
397 f.write(' { %-50s %7d },\n' % (key, schema))
398 f.write('};\n\n')
399
400 f.write('const internal::PropertiesNode kProperties[] = {\n'
401 '// Begin End Additional Properties\n')
402 for node in self.properties_nodes:
403 f.write(' { %5d, %5d, %5d }, // %s\n' % node)
404 f.write('};\n\n')
405
406 f.write('const internal::SchemaData kChromeSchemaData = {\n'
407 ' kSchemas,\n'
408 ' kPropertyNodes,\n'
409 ' kProperties,\n'
410 '};\n\n')
411
412
266 def _WritePolicyConstantSource(policies, os, f): 413 def _WritePolicyConstantSource(policies, os, f):
267 f.write('#include "base/basictypes.h"\n' 414 f.write('#include "base/basictypes.h"\n'
268 '#include "base/logging.h"\n' 415 '#include "base/logging.h"\n'
416 '#include "components/policy/core/common/schema_internal.h"\n'
269 '#include "policy/policy_constants.h"\n' 417 '#include "policy/policy_constants.h"\n'
270 '\n' 418 '\n'
271 'namespace policy {\n\n') 419 'namespace policy {\n'
420 '\n'
421 'namespace {\n'
422 '\n')
272 423
273 f.write('namespace {\n\n') 424 # Generate the Chrome schema.
425 chrome_schema = {
426 'type': 'object',
427 'properties': {},
428 }
429 shared_strings = {}
430 for policy in policies:
431 shared_strings[policy.name] = "key::k%s" % policy.name
432 if policy.is_supported:
433 chrome_schema['properties'][policy.name] = policy.schema
274 434
275 f.write('const PolicyDefinitionList::Entry kEntries[] = {\n') 435 f.write('const PolicyDefinitionList::Entry kEntries[] = {\n')
276 for policy in policies: 436 for policy in policies:
277 if policy.is_supported: 437 if policy.is_supported:
278 f.write(' { key::k%s, base::Value::%s, %s, %s, %s },\n' % 438 f.write(' { key::k%s, base::Value::%s, %s, %s, %s },\n' %
279 (policy.name, _GetValueType(policy.policy_type), 439 (policy.name, _GetValueType(policy.policy_type),
280 'true' if policy.is_device_only else 'false', policy.id, 440 'true' if policy.is_device_only else 'false', policy.id,
281 policy.max_size)) 441 policy.max_size))
282 f.write('};\n\n') 442 f.write('};\n\n')
283 443
284 f.write('const PolicyDefinitionList kChromePolicyList = {\n' 444 f.write('const PolicyDefinitionList kChromePolicyList = {\n'
285 ' kEntries,\n' 445 ' kEntries,\n'
286 ' kEntries + arraysize(kEntries),\n' 446 ' kEntries + arraysize(kEntries),\n'
287 '};\n\n') 447 '};\n\n')
288 448
289 has_deprecated_policies = any( 449 has_deprecated_policies = any(
290 [p.is_supported and p.is_deprecated for p in policies]) 450 [p.is_supported and p.is_deprecated for p in policies])
291 451
292 if has_deprecated_policies: 452 if has_deprecated_policies:
293 f.write('// List of deprecated policies.\n' 453 f.write('// List of deprecated policies.\n'
294 'const char* kDeprecatedPolicyList[] = {\n') 454 'const char* kDeprecatedPolicyList[] = {\n')
295 for policy in policies: 455 for policy in policies:
296 if policy.is_supported and policy.is_deprecated: 456 if policy.is_supported and policy.is_deprecated:
297 f.write(' key::k%s,\n' % policy.name) 457 f.write(' key::k%s,\n' % policy.name)
298 f.write('};\n\n') 458 f.write('};\n\n')
299 459
460 schema_generator = SchemaNodesGenerator(shared_strings)
461 schema_generator.Generate(chrome_schema, 'root node')
462 schema_generator.Write(f)
463
300 f.write('} // namespace\n\n') 464 f.write('} // namespace\n\n')
301 465
302 if os == 'win': 466 if os == 'win':
303 f.write('#if defined(GOOGLE_CHROME_BUILD)\n' 467 f.write('#if defined(GOOGLE_CHROME_BUILD)\n'
304 'const wchar_t kRegistryChromePolicyKey[] = ' 468 'const wchar_t kRegistryChromePolicyKey[] = '
305 'L"' + CHROME_POLICY_KEY + '";\n' 469 'L"' + CHROME_POLICY_KEY + '";\n'
306 '#else\n' 470 '#else\n'
307 'const wchar_t kRegistryChromePolicyKey[] = ' 471 'const wchar_t kRegistryChromePolicyKey[] = '
308 'L"' + CHROMIUM_POLICY_KEY + '";\n' 472 'L"' + CHROMIUM_POLICY_KEY + '";\n'
309 '#endif\n\n') 473 '#endif\n\n')
310 474
311 f.write('bool IsDeprecatedPolicy(const std::string& policy) {\n') 475 f.write('bool IsDeprecatedPolicy(const std::string& policy) {\n')
312 if has_deprecated_policies: 476 if has_deprecated_policies:
313 # arraysize() doesn't work with empty arrays. 477 # arraysize() doesn't work with empty arrays.
314 f.write(' for (size_t i = 0; i < arraysize(kDeprecatedPolicyList);' 478 f.write(' for (size_t i = 0; i < arraysize(kDeprecatedPolicyList);'
315 ' ++i) {\n' 479 ' ++i) {\n'
316 ' if (policy == kDeprecatedPolicyList[i])\n' 480 ' if (policy == kDeprecatedPolicyList[i])\n'
317 ' return true;\n' 481 ' return true;\n'
318 ' }\n') 482 ' }\n')
319 f.write(' return false;\n' 483 f.write(' return false;\n'
320 '}\n\n') 484 '}\n\n')
321 485
322 f.write('const PolicyDefinitionList* GetChromePolicyDefinitionList() {\n' 486 f.write('const PolicyDefinitionList* GetChromePolicyDefinitionList() {\n'
323 ' return &kChromePolicyList;\n' 487 ' return &kChromePolicyList;\n'
324 '}\n\n') 488 '}\n\n')
325 489
490 f.write('const internal::SchemaData* GetChromeSchemaData() {\n'
491 ' return &kChromeSchemaData;\n'
492 '}\n\n')
493
326 f.write('namespace key {\n\n') 494 f.write('namespace key {\n\n')
327 for policy in policies: 495 for policy in policies:
328 # TODO(joaodasilva): Include only supported policies in 496 # TODO(joaodasilva): Include only supported policies in
329 # configuration_policy_handler.cc and configuration_policy_handler_list.cc 497 # configuration_policy_handler.cc and configuration_policy_handler_list.cc
330 # so that these names can be conditional on 'policy.is_supported'. 498 # so that these names can be conditional on 'policy.is_supported'.
331 # http://crbug.com/223616 499 # http://crbug.com/223616
332 f.write('const char k{name}[] = "{name}";\n'.format(name=policy.name)) 500 f.write('const char k{name}[] = "{name}";\n'.format(name=policy.name))
333 f.write('\n} // namespace key\n\n' 501 f.write('\n} // namespace key\n\n'
334 '} // namespace policy\n') 502 '} // namespace policy\n')
335 503
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 def _WriteCloudPolicyDecoder(policies, os, f): 746 def _WriteCloudPolicyDecoder(policies, os, f):
579 f.write(CPP_HEAD) 747 f.write(CPP_HEAD)
580 for policy in policies: 748 for policy in policies:
581 if policy.is_supported and not policy.is_device_only: 749 if policy.is_supported and not policy.is_device_only:
582 _WritePolicyCode(f, policy) 750 _WritePolicyCode(f, policy)
583 f.write(CPP_FOOT) 751 f.write(CPP_FOOT)
584 752
585 753
586 if __name__ == '__main__': 754 if __name__ == '__main__':
587 sys.exit(main()) 755 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698