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

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

Issue 138003003: Add additional restriction to policy schema internal (part1) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: more fixes Created 6 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/resources/policy_templates.json ('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
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 250
251 # A mapping of the simple schema types to base::Value::Types. 251 # A mapping of the simple schema types to base::Value::Types.
252 SIMPLE_SCHEMA_NAME_MAP = { 252 SIMPLE_SCHEMA_NAME_MAP = {
253 'boolean': 'TYPE_BOOLEAN', 253 'boolean': 'TYPE_BOOLEAN',
254 'integer': 'TYPE_INTEGER', 254 'integer': 'TYPE_INTEGER',
255 'null' : 'TYPE_NULL', 255 'null' : 'TYPE_NULL',
256 'number' : 'TYPE_DOUBLE', 256 'number' : 'TYPE_DOUBLE',
257 'string' : 'TYPE_STRING', 257 'string' : 'TYPE_STRING',
258 } 258 }
259 259
260
261 class SchemaNodesGenerator: 260 class SchemaNodesGenerator:
262 """Builds the internal structs to represent a JSON schema.""" 261 """Builds the internal structs to represent a JSON schema."""
263 262
264 def __init__(self, shared_strings): 263 def __init__(self, shared_strings):
265 """Creates a new generator. 264 """Creates a new generator.
266 265
267 |shared_strings| is a map of strings to a C expression that evaluates to 266 |shared_strings| is a map of strings to a C expression that evaluates to
268 that string at runtime. This mapping can be used to reuse existing string 267 that string at runtime. This mapping can be used to reuse existing string
269 constants.""" 268 constants."""
270 self.shared_strings = shared_strings 269 self.shared_strings = shared_strings
271 self.schema_nodes = [] 270 self.schema_nodes = []
272 self.property_nodes = [] 271 self.property_nodes = []
273 self.properties_nodes = [] 272 self.properties_nodes = []
273 self.restriction_nodes = []
274 self.int_enums = []
275 self.string_enums = []
274 self.simple_types = { 276 self.simple_types = {
275 'boolean': None, 277 'boolean': None,
276 'integer': None, 278 'integer': None,
277 'null': None, 279 'null': None,
278 'number': None, 280 'number': None,
279 'string': None, 281 'string': None,
280 } 282 }
281 self.stringlist_type = None 283 self.stringlist_type = None
284 self.ranges = {}
282 285
283 def GetString(self, s): 286 def GetString(self, s):
284 return self.shared_strings[s] if s in self.shared_strings else '"%s"' % s 287 return self.shared_strings[s] if s in self.shared_strings else '"%s"' % s
285 288
286 def AppendSchema(self, type, extra, comment=''): 289 def AppendSchema(self, type, extra, comment=''):
287 index = len(self.schema_nodes) 290 index = len(self.schema_nodes)
288 self.schema_nodes.append((type, extra, comment)) 291 self.schema_nodes.append((type, extra, comment))
289 return index 292 return index
290 293
294 def AppendRestriction(self, first, second):
295 r = (str(first), str(second))
296 if not r in self.ranges:
297 self.ranges[r] = len(self.restriction_nodes)
298 self.restriction_nodes.append(r)
299 return self.ranges[r]
300
291 def GetSimpleType(self, name): 301 def GetSimpleType(self, name):
292 if self.simple_types[name] == None: 302 if self.simple_types[name] == None:
293 self.simple_types[name] = self.AppendSchema( 303 self.simple_types[name] = self.AppendSchema(
294 SIMPLE_SCHEMA_NAME_MAP[name], 304 SIMPLE_SCHEMA_NAME_MAP[name],
295 -1, 305 -1,
296 'simple type: ' + name) 306 'simple type: ' + name)
297 return self.simple_types[name] 307 return self.simple_types[name]
298 308
299 def GetStringList(self): 309 def GetStringList(self):
300 if self.stringlist_type == None: 310 if self.stringlist_type == None:
301 self.stringlist_type = self.AppendSchema( 311 self.stringlist_type = self.AppendSchema(
302 'TYPE_LIST', 312 'TYPE_LIST',
303 self.GetSimpleType('string'), 313 self.GetSimpleType('string'),
304 'simple type: stringlist') 314 'simple type: stringlist')
305 return self.stringlist_type 315 return self.stringlist_type
306 316
317 def SchemaHaveRestriction(self, schema):
318 return 'minimum' in schema or 'maximum' in schema or 'enum' in schema
319
320 def IsConsecutiveInterval(self, seq):
321 sortedSeq = sorted(seq)
322 return all(sortedSeq[i] + 1 == sortedSeq[i + 1]
323 for i in xrange(len(sortedSeq) - 1))
324
325 def GetEnumIntegerType(self, schema, name):
326 assert all(type(x) == int for x in schema['enum'])
327 possible_values = schema['enum']
328 if self.IsConsecutiveInterval(possible_values):
329 index = self.AppendRestriction(max(possible_values), min(possible_values))
330 return self.AppendSchema('TYPE_INTEGER', index,
331 'integer with enumeration restriction (use range instead): %s' % name)
332 offset_begin = len(self.int_enums)
333 self.int_enums += possible_values
334 offset_end = len(self.int_enums)
335 return self.AppendSchema('TYPE_INTEGER',
336 self.AppendRestriction(offset_begin, offset_end),
337 'integer with enumeration restriction: %s' % name)
338
339 def GetEnumStringType(self, schema, name):
340 assert all(type(x) == str for x in schema['enum'])
341 offset_begin = len(self.string_enums)
342 self.string_enums += schema['enum']
343 offset_end = len(self.string_enums)
344 return self.AppendSchema('TYPE_STRING',
345 self.AppendRestriction(offset_begin, offset_end),
346 'string with enumeration restriction: %s' % name)
347
348 def GetEnumType(self, schema, name):
349 if len(schema['enum']) == 0:
350 raise RuntimeError('Empty enumeration in %s' % name)
351 elif schema['type'] == 'integer':
352 return self.GetEnumIntegerType(schema, name)
353 elif schema['type'] == 'string':
354 return self.GetEnumStringType(schema, name)
355 else:
356 raise RuntimeError('Unknown enumeration type in %s' % name)
357
358 def GetRangedType(self, schema, name):
359 if schema['type'] != 'integer':
360 raise RuntimeError('Unknown ranged type in %s' % name)
361 min_value_set, max_value_set = False, False
362 if 'minimum' in schema:
363 min_value = int(schema['minimum'])
364 min_value_set = True
365 if 'maximum' in schema:
366 max_value = int(schema['minimum'])
367 max_value_set = True
368 if min_value_set and max_value_set and min_value > max_value:
369 raise RuntimeError('Invalid ranged type in %s' % name)
370 index = self.AppendRestriction(
371 str(max_value) if max_value_set else 'INT_MAX',
372 str(min_value) if min_value_set else 'INT_MIN')
373 return self.AppendSchema('TYPE_INTEGER',
374 index,
375 'integer with ranged restriction: %s' % name)
376
307 def Generate(self, schema, name): 377 def Generate(self, schema, name):
308 """Generates the structs for the given schema. 378 """Generates the structs for the given schema.
309 379
310 |schema|: a valid JSON schema in a dictionary. 380 |schema|: a valid JSON schema in a dictionary.
311 |name|: the name of the current node, for the generated comments.""" 381 |name|: the name of the current node, for the generated comments."""
312 # Simple types use shared nodes.
313 if schema['type'] in self.simple_types: 382 if schema['type'] in self.simple_types:
314 return self.GetSimpleType(schema['type']) 383 if not self.SchemaHaveRestriction(schema):
384 # Simple types use shared nodes.
385 return self.GetSimpleType(schema['type'])
386 elif 'enum' in schema:
387 return self.GetEnumType(schema, name)
388 else:
389 return self.GetRangedType(schema, name)
315 390
316 if schema['type'] == 'array': 391 if schema['type'] == 'array':
317 # Special case for lists of strings, which is a common policy type. 392 # Special case for lists of strings, which is a common policy type.
318 if schema['items']['type'] == 'string': 393 if schema['items']['type'] == 'string':
319 return self.GetStringList() 394 return self.GetStringList()
320 return self.AppendSchema( 395 return self.AppendSchema(
321 'TYPE_LIST', 396 'TYPE_LIST',
322 self.Generate(schema['items'], 'items of ' + name)) 397 self.Generate(schema['items'], 'items of ' + name))
323 elif schema['type'] == 'object': 398 elif schema['type'] == 'object':
324 # Reserve an index first, so that dictionaries come before their 399 # Reserve an index first, so that dictionaries come before their
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 key += ',' 448 key += ','
374 f.write(' { %-50s %7d },\n' % (key, schema)) 449 f.write(' { %-50s %7d },\n' % (key, schema))
375 f.write('};\n\n') 450 f.write('};\n\n')
376 451
377 f.write('const internal::PropertiesNode kProperties[] = {\n' 452 f.write('const internal::PropertiesNode kProperties[] = {\n'
378 '// Begin End Additional Properties\n') 453 '// Begin End Additional Properties\n')
379 for node in self.properties_nodes: 454 for node in self.properties_nodes:
380 f.write(' { %5d, %5d, %5d }, // %s\n' % node) 455 f.write(' { %5d, %5d, %5d }, // %s\n' % node)
381 f.write('};\n\n') 456 f.write('};\n\n')
382 457
458 f.write('const internal::RestrictionNode kRestrictionNodes[] = {\n')
459 f.write('// FIRST, SECOND\n')
460 for first, second in self.restriction_nodes:
461 f.write(' {{ %-8s %4s}},\n' % (first + ',', second))
462 f.write('};\n\n')
463
464 f.write('const int kIntegerEnumerations[] = {\n')
465 for possible_values in self.int_enums:
466 f.write(' %d,\n' % possible_values)
467 f.write('};\n\n')
468
469 f.write('const char* kStringEnumerations[] = {\n')
470 for possible_values in self.string_enums:
471 f.write(' %s,\n' % self.GetString(possible_values))
472 f.write('};\n\n')
473
383 f.write('const internal::SchemaData kChromeSchemaData = {\n' 474 f.write('const internal::SchemaData kChromeSchemaData = {\n'
384 ' kSchemas,\n' 475 ' kSchemas,\n'
385 ' kPropertyNodes,\n' 476 ' kPropertyNodes,\n'
386 ' kProperties,\n' 477 ' kProperties,\n');
387 '};\n\n') 478 f.write(' kRestrictionNodes,\n' if self.restriction_nodes else ' NULL,\n')
479 f.write(' kIntegerEnumerations,\n' if self.int_enums else ' NULL,\n')
480 f.write(' kStringEnumerations,\n' if self.string_enums else ' NULL,\n')
481 f.write('};\n\n')
388 482
389 483
390 def _WritePolicyConstantSource(policies, os, f): 484 def _WritePolicyConstantSource(policies, os, f):
391 f.write('#include "policy/policy_constants.h"\n' 485 f.write('#include "policy/policy_constants.h"\n'
392 '\n' 486 '\n'
393 '#include <algorithm>\n' 487 '#include <algorithm>\n'
488 '#include <climits>\n'
394 '\n' 489 '\n'
395 '#include "base/logging.h"\n' 490 '#include "base/logging.h"\n'
396 '#include "components/policy/core/common/schema_internal.h"\n' 491 '#include "components/policy/core/common/schema_internal.h"\n'
397 '\n' 492 '\n'
398 'namespace policy {\n' 493 'namespace policy {\n'
399 '\n' 494 '\n'
400 'namespace {\n' 495 'namespace {\n'
401 '\n') 496 '\n')
402 497
403 # Generate the Chrome schema. 498 # Generate the Chrome schema.
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 def _WriteCloudPolicyDecoder(policies, os, f): 834 def _WriteCloudPolicyDecoder(policies, os, f):
740 f.write(CPP_HEAD) 835 f.write(CPP_HEAD)
741 for policy in policies: 836 for policy in policies:
742 if policy.is_supported and not policy.is_device_only: 837 if policy.is_supported and not policy.is_device_only:
743 _WritePolicyCode(f, policy) 838 _WritePolicyCode(f, policy)
744 f.write(CPP_FOOT) 839 f.write(CPP_FOOT)
745 840
746 841
747 if __name__ == '__main__': 842 if __name__ == '__main__':
748 sys.exit(main()) 843 sys.exit(main())
OLDNEW
« no previous file with comments | « components/policy/resources/policy_templates.json ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698