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

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: 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
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
282 284
283 def GetString(self, s): 285 def GetString(self, s):
284 return self.shared_strings[s] if s in self.shared_strings else '"%s"' % s 286 return self.shared_strings[s] if s in self.shared_strings else '"%s"' % s
285 287
286 def AppendSchema(self, type, extra, comment=''): 288 def AppendSchema(self, type, extra, comment=''):
287 index = len(self.schema_nodes) 289 index = len(self.schema_nodes)
288 self.schema_nodes.append((type, extra, comment)) 290 self.schema_nodes.append((type, extra, comment))
289 return index 291 return index
290 292
293 def AppendRestriction(self, first, second):
294 index = len(self.restriction_nodes)
295 self.restriction_nodes.append((str(first), str(second)))
296 return index
Joao da Silva 2014/01/20 10:49:10 If you look at the output you'll see that there ar
binjin 2014/01/20 14:09:23 Done.
297
291 def GetSimpleType(self, name): 298 def GetSimpleType(self, name):
292 if self.simple_types[name] == None: 299 if self.simple_types[name] == None:
293 self.simple_types[name] = self.AppendSchema( 300 self.simple_types[name] = self.AppendSchema(
294 SIMPLE_SCHEMA_NAME_MAP[name], 301 SIMPLE_SCHEMA_NAME_MAP[name],
295 -1, 302 -1,
296 'simple type: ' + name) 303 'simple type: ' + name)
297 return self.simple_types[name] 304 return self.simple_types[name]
298 305
299 def GetStringList(self): 306 def GetStringList(self):
300 if self.stringlist_type == None: 307 if self.stringlist_type == None:
301 self.stringlist_type = self.AppendSchema( 308 self.stringlist_type = self.AppendSchema(
302 'TYPE_LIST', 309 'TYPE_LIST',
303 self.GetSimpleType('string'), 310 self.GetSimpleType('string'),
304 'simple type: stringlist') 311 'simple type: stringlist')
305 return self.stringlist_type 312 return self.stringlist_type
306 313
314 def SchemaHaveRestriction(self, schema):
315 return 'minimum' in schema or 'maximum' in schema or 'enum' in schema
316
317 def isConsecutiveInterval(self, seq):
Joao da Silva 2014/01/20 10:49:10 Start the function name with a capital letter:
binjin 2014/01/20 14:09:23 Done.
318 if len(seq) == 1:
319 return True
Joao da Silva 2014/01/20 10:49:10 This special case is not needed; xrange(0) will be
binjin 2014/01/20 14:09:23 Done.
320 sortedSeq = sorted(seq)
321 return all(sortedSeq[i] + 1 == sortedSeq[i + 1]
322 for i in xrange(len(sortedSeq) - 1))
323
324 def GetEnumIntegerType(self, schema, name):
325 assert all(type(x) == int for x in schema['enum'])
326 possible_values = schema['enum']
327 if self.isConsecutiveInterval(possible_values):
328 index = self.AppendRestriction(max(possible_values), min(possible_values))
329 return self.AppendSchema('TYPE_INTEGER', index,
330 'integer with enumeration restriction(use ranged instead): %s' % name)
Joao da Silva 2014/01/20 10:49:10 nit: space before (, "used range instead":
binjin 2014/01/20 14:09:23 Done.
331 offset_begin = len(self.int_enums)
332 self.int_enums += possible_values
333 offset_end = len(self.int_enums)
334 return self.AppendSchema('TYPE_INTEGER',
335 self.AppendRestriction(offset_begin, offset_end),
336 'integer with enumeration restriction: %s' % name)
337
338 def GetEnumStringType(self, schema, name):
339 assert all(type(x) == str for x in schema['enum'])
340 offset_begin = len(self.string_enums)
341 self.string_enums += schema['enum']
342 offset_end = len(self.string_enums)
343 return self.AppendSchema('TYPE_STRING',
344 self.AppendRestriction(offset_begin, offset_end),
345 'string with enumeration restriction: %s' % name)
346
347 def GetEnumType(self, schema, name):
348 if len(schema['enum']) == 0:
349 raise RuntimeError('Empty enumeration in %s' % name)
350 elif schema['type'] == 'integer':
351 return self.GetEnumIntegerType(schema, name)
352 elif schema['type'] == 'string':
353 return self.GetEnumStringType(schema, name)
354 else:
355 raise RuntimeError('Unknown enumeration type in %s' % name)
356
357 def GetRangedType(self, schema, name):
358 if schema['type'] != 'integer':
359 raise RuntimeError('Unknown ranged type in %s' % name)
360 min_value_set, max_value_set = False, False
361 if 'minimum' in schema:
362 min_value = int(schema['minimum'])
363 min_value_set = True
364 if 'maximum' in schema:
365 max_value = int(schema['minimum'])
366 max_value_set = True
367 if min_value_set and max_value_set and min_value > max_value:
368 raise RuntimeError('Invalid ranged type in %s' % name)
369 index = self.AppendRestriction(
370 str(max_value) if max_value_set else 'INT_MAX',
371 str(min_value) if min_value_set else 'INT_MIN')
372 return self.AppendSchema('TYPE_INTEGER',
373 index,
374 'integer with ranged restriction: %s' % name)
375
307 def Generate(self, schema, name): 376 def Generate(self, schema, name):
308 """Generates the structs for the given schema. 377 """Generates the structs for the given schema.
309 378
310 |schema|: a valid JSON schema in a dictionary. 379 |schema|: a valid JSON schema in a dictionary.
311 |name|: the name of the current node, for the generated comments.""" 380 |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: 381 if schema['type'] in self.simple_types:
314 return self.GetSimpleType(schema['type']) 382 if not self.SchemaHaveRestriction(schema):
383 # Simple types use shared nodes.
384 return self.GetSimpleType(schema['type'])
385 elif 'enum' in schema:
386 return self.GetEnumType(schema, name)
387 else:
388 return self.GetRangedType(schema, name)
315 389
316 if schema['type'] == 'array': 390 if schema['type'] == 'array':
317 # Special case for lists of strings, which is a common policy type. 391 # Special case for lists of strings, which is a common policy type.
318 if schema['items']['type'] == 'string': 392 if schema['items']['type'] == 'string':
319 return self.GetStringList() 393 return self.GetStringList()
320 return self.AppendSchema( 394 return self.AppendSchema(
321 'TYPE_LIST', 395 'TYPE_LIST',
322 self.Generate(schema['items'], 'items of ' + name)) 396 self.Generate(schema['items'], 'items of ' + name))
323 elif schema['type'] == 'object': 397 elif schema['type'] == 'object':
324 # Reserve an index first, so that dictionaries come before their 398 # Reserve an index first, so that dictionaries come before their
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 key += ',' 447 key += ','
374 f.write(' { %-50s %7d },\n' % (key, schema)) 448 f.write(' { %-50s %7d },\n' % (key, schema))
375 f.write('};\n\n') 449 f.write('};\n\n')
376 450
377 f.write('const internal::PropertiesNode kProperties[] = {\n' 451 f.write('const internal::PropertiesNode kProperties[] = {\n'
378 '// Begin End Additional Properties\n') 452 '// Begin End Additional Properties\n')
379 for node in self.properties_nodes: 453 for node in self.properties_nodes:
380 f.write(' { %5d, %5d, %5d }, // %s\n' % node) 454 f.write(' { %5d, %5d, %5d }, // %s\n' % node)
381 f.write('};\n\n') 455 f.write('};\n\n')
382 456
457 f.write('const internal::RestrictionNode kRestrictionNodes[] = {\n')
458 f.write('// FIRST, SECOND\n')
459 for first, second in self.restriction_nodes:
460 f.write(' {{ %-8s %4s}},\n' % (first + ',', second))
461 f.write('};\n\n')
462
463 f.write('const int kIntegerEnumerations[] = {\n')
464 for possible_values in self.int_enums:
465 f.write(' %d,\n' % possible_values)
466 f.write('};\n\n')
467
468 f.write('const char* kStringEnumerations[] = {\n')
469 for possible_values in self.string_enums:
470 f.write(' %s,\n' % self.GetString(possible_values))
471 f.write('};\n\n')
472
383 f.write('const internal::SchemaData kChromeSchemaData = {\n' 473 f.write('const internal::SchemaData kChromeSchemaData = {\n'
384 ' kSchemas,\n' 474 ' kSchemas,\n'
385 ' kPropertyNodes,\n' 475 ' kPropertyNodes,\n'
386 ' kProperties,\n' 476 ' kProperties,\n');
387 '};\n\n') 477 f.write(' kRestrictionNodes,\n' if self.restriction_nodes else ' NULL,\n')
478 f.write(' kIntegerEnumerations,\n' if self.int_enums else ' NULL,\n')
479 f.write(' kStringEnumerations,\n' if self.string_enums else ' NULL,\n')
480 f.write('};\n\n')
388 481
389 482
390 def _WritePolicyConstantSource(policies, os, f): 483 def _WritePolicyConstantSource(policies, os, f):
391 f.write('#include "policy/policy_constants.h"\n' 484 f.write('#include "policy/policy_constants.h"\n'
392 '\n' 485 '\n'
393 '#include <algorithm>\n' 486 '#include <algorithm>\n'
487 '#include <climits>\n'
394 '\n' 488 '\n'
395 '#include "base/logging.h"\n' 489 '#include "base/logging.h"\n'
396 '#include "components/policy/core/common/schema_internal.h"\n' 490 '#include "components/policy/core/common/schema_internal.h"\n'
397 '\n' 491 '\n'
398 'namespace policy {\n' 492 'namespace policy {\n'
399 '\n' 493 '\n'
400 'namespace {\n' 494 'namespace {\n'
401 '\n') 495 '\n')
402 496
403 # Generate the Chrome schema. 497 # Generate the Chrome schema.
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 def _WriteCloudPolicyDecoder(policies, os, f): 833 def _WriteCloudPolicyDecoder(policies, os, f):
740 f.write(CPP_HEAD) 834 f.write(CPP_HEAD)
741 for policy in policies: 835 for policy in policies:
742 if policy.is_supported and not policy.is_device_only: 836 if policy.is_supported and not policy.is_device_only:
743 _WritePolicyCode(f, policy) 837 _WritePolicyCode(f, policy)
744 f.write(CPP_FOOT) 838 f.write(CPP_FOOT)
745 839
746 840
747 if __name__ == '__main__': 841 if __name__ == '__main__':
748 sys.exit(main()) 842 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698