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

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 Created 7 years, 1 month 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
« no previous file with comments | « chrome/chrome_tests_unit.gypi ('k') | components/policy/core/common/schema.h » ('j') | 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
(...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:
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 # Note that |properties| must be evaluated immediately, so that all the
358 # recursive calls to Generate() append the necessary child nodes; if
359 # |properties| were a generator then this wouldn't work.
360 sorted_properties = sorted(schema.get('properties', {}).items())
361 properties = [ (self.GetString(key), self.Generate(schema, key))
362 for key, schema in sorted_properties ]
363 begin = len(self.property_nodes)
364 self.property_nodes += properties
365 end = len(self.property_nodes)
366
367 extra = len(self.properties_nodes)
368 self.properties_nodes.append((begin, end, additionalProperties, name))
369
370 # Set the right data at |index| now.
371 self.schema_nodes[index] = ('TYPE_DICTIONARY', extra, name)
372 return index
373 else:
374 assert False
375
376 def Write(self, f):
377 """Writes the generated structs to the given file.
378
379 |f| an open file to write to."""
380 f.write('const internal::SchemaNode kSchemas[] = {\n'
381 '// Type Extra\n')
382 for type, extra, comment in self.schema_nodes:
383 type += ','
384 f.write(' { base::Value::%-18s %3d }, // %s\n' % (type, extra, comment))
385 f.write('};\n\n')
386
387 f.write('const internal::PropertyNode kPropertyNodes[] = {\n'
388 '// Property #Schema\n')
389 for key, schema in self.property_nodes:
390 key += ','
391 f.write(' { %-50s %7d },\n' % (key, schema))
392 f.write('};\n\n')
393
394 f.write('const internal::PropertiesNode kProperties[] = {\n'
395 '// Begin End Additional Properties\n')
396 for node in self.properties_nodes:
397 f.write(' { %5d, %5d, %5d }, // %s\n' % node)
398 f.write('};\n\n')
399
400 f.write('const internal::SchemaData kChromeSchemaData = {\n'
401 ' kSchemas,\n'
402 ' kPropertyNodes,\n'
403 ' kProperties,\n'
404 '};\n\n')
405
406
266 def _WritePolicyConstantSource(policies, os, f): 407 def _WritePolicyConstantSource(policies, os, f):
267 f.write('#include "base/basictypes.h"\n' 408 f.write('#include "base/basictypes.h"\n'
268 '#include "base/logging.h"\n' 409 '#include "base/logging.h"\n'
410 '#include "components/policy/core/common/schema_internal.h"\n'
269 '#include "policy/policy_constants.h"\n' 411 '#include "policy/policy_constants.h"\n'
270 '\n' 412 '\n'
271 'namespace policy {\n\n') 413 'namespace policy {\n'
414 '\n'
415 'namespace {\n'
416 '\n')
272 417
273 f.write('namespace {\n\n') 418 # Generate the Chrome schema.
419 chrome_schema = {
420 'type': 'object',
421 'properties': {},
422 }
423 shared_strings = {}
424 for policy in policies:
425 shared_strings[policy.name] = "key::k%s" % policy.name
426 if policy.is_supported:
427 chrome_schema['properties'][policy.name] = policy.schema
274 428
275 f.write('const PolicyDefinitionList::Entry kEntries[] = {\n') 429 f.write('const PolicyDefinitionList::Entry kEntries[] = {\n')
276 for policy in policies: 430 for policy in policies:
277 if policy.is_supported: 431 if policy.is_supported:
278 f.write(' { key::k%s, base::Value::%s, %s, %s, %s },\n' % 432 f.write(' { key::k%s, base::Value::%s, %s, %s, %s },\n' %
279 (policy.name, _GetValueType(policy.policy_type), 433 (policy.name, _GetValueType(policy.policy_type),
280 'true' if policy.is_device_only else 'false', policy.id, 434 'true' if policy.is_device_only else 'false', policy.id,
281 policy.max_size)) 435 policy.max_size))
282 f.write('};\n\n') 436 f.write('};\n\n')
283 437
284 f.write('const PolicyDefinitionList kChromePolicyList = {\n' 438 f.write('const PolicyDefinitionList kChromePolicyList = {\n'
285 ' kEntries,\n' 439 ' kEntries,\n'
286 ' kEntries + arraysize(kEntries),\n' 440 ' kEntries + arraysize(kEntries),\n'
287 '};\n\n') 441 '};\n\n')
288 442
289 has_deprecated_policies = any( 443 has_deprecated_policies = any(
290 [p.is_supported and p.is_deprecated for p in policies]) 444 [p.is_supported and p.is_deprecated for p in policies])
291 445
292 if has_deprecated_policies: 446 if has_deprecated_policies:
293 f.write('// List of deprecated policies.\n' 447 f.write('// List of deprecated policies.\n'
294 'const char* kDeprecatedPolicyList[] = {\n') 448 'const char* kDeprecatedPolicyList[] = {\n')
295 for policy in policies: 449 for policy in policies:
296 if policy.is_supported and policy.is_deprecated: 450 if policy.is_supported and policy.is_deprecated:
297 f.write(' key::k%s,\n' % policy.name) 451 f.write(' key::k%s,\n' % policy.name)
298 f.write('};\n\n') 452 f.write('};\n\n')
299 453
454 schema_generator = SchemaNodesGenerator(shared_strings)
455 schema_generator.Generate(chrome_schema, 'root node')
456 schema_generator.Write(f)
457
300 f.write('} // namespace\n\n') 458 f.write('} // namespace\n\n')
301 459
302 if os == 'win': 460 if os == 'win':
303 f.write('#if defined(GOOGLE_CHROME_BUILD)\n' 461 f.write('#if defined(GOOGLE_CHROME_BUILD)\n'
304 'const wchar_t kRegistryChromePolicyKey[] = ' 462 'const wchar_t kRegistryChromePolicyKey[] = '
305 'L"' + CHROME_POLICY_KEY + '";\n' 463 'L"' + CHROME_POLICY_KEY + '";\n'
306 '#else\n' 464 '#else\n'
307 'const wchar_t kRegistryChromePolicyKey[] = ' 465 'const wchar_t kRegistryChromePolicyKey[] = '
308 'L"' + CHROMIUM_POLICY_KEY + '";\n' 466 'L"' + CHROMIUM_POLICY_KEY + '";\n'
309 '#endif\n\n') 467 '#endif\n\n')
310 468
311 f.write('bool IsDeprecatedPolicy(const std::string& policy) {\n') 469 f.write('bool IsDeprecatedPolicy(const std::string& policy) {\n')
312 if has_deprecated_policies: 470 if has_deprecated_policies:
313 # arraysize() doesn't work with empty arrays. 471 # arraysize() doesn't work with empty arrays.
314 f.write(' for (size_t i = 0; i < arraysize(kDeprecatedPolicyList);' 472 f.write(' for (size_t i = 0; i < arraysize(kDeprecatedPolicyList);'
315 ' ++i) {\n' 473 ' ++i) {\n'
316 ' if (policy == kDeprecatedPolicyList[i])\n' 474 ' if (policy == kDeprecatedPolicyList[i])\n'
317 ' return true;\n' 475 ' return true;\n'
318 ' }\n') 476 ' }\n')
319 f.write(' return false;\n' 477 f.write(' return false;\n'
320 '}\n\n') 478 '}\n\n')
321 479
322 f.write('const PolicyDefinitionList* GetChromePolicyDefinitionList() {\n' 480 f.write('const PolicyDefinitionList* GetChromePolicyDefinitionList() {\n'
323 ' return &kChromePolicyList;\n' 481 ' return &kChromePolicyList;\n'
324 '}\n\n') 482 '}\n\n')
325 483
484 f.write('const internal::SchemaData* GetChromeSchemaData() {\n'
485 ' return &kChromeSchemaData;\n'
486 '}\n\n')
487
326 f.write('namespace key {\n\n') 488 f.write('namespace key {\n\n')
327 for policy in policies: 489 for policy in policies:
328 # TODO(joaodasilva): Include only supported policies in 490 # TODO(joaodasilva): Include only supported policies in
329 # configuration_policy_handler.cc and configuration_policy_handler_list.cc 491 # configuration_policy_handler.cc and configuration_policy_handler_list.cc
330 # so that these names can be conditional on 'policy.is_supported'. 492 # so that these names can be conditional on 'policy.is_supported'.
331 # http://crbug.com/223616 493 # http://crbug.com/223616
332 f.write('const char k{name}[] = "{name}";\n'.format(name=policy.name)) 494 f.write('const char k{name}[] = "{name}";\n'.format(name=policy.name))
333 f.write('\n} // namespace key\n\n' 495 f.write('\n} // namespace key\n\n'
334 '} // namespace policy\n') 496 '} // namespace policy\n')
335 497
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 def _WriteCloudPolicyDecoder(policies, os, f): 740 def _WriteCloudPolicyDecoder(policies, os, f):
579 f.write(CPP_HEAD) 741 f.write(CPP_HEAD)
580 for policy in policies: 742 for policy in policies:
581 if policy.is_supported and not policy.is_device_only: 743 if policy.is_supported and not policy.is_device_only:
582 _WritePolicyCode(f, policy) 744 _WritePolicyCode(f, policy)
583 f.write(CPP_FOOT) 745 f.write(CPP_FOOT)
584 746
585 747
586 if __name__ == '__main__': 748 if __name__ == '__main__':
587 sys.exit(main()) 749 sys.exit(main())
OLDNEW
« no previous file with comments | « chrome/chrome_tests_unit.gypi ('k') | components/policy/core/common/schema.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698