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

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

Powered by Google App Engine
This is Rietveld 408576698