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

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: fix python generator and C++ parser 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((first, second))
296 return index
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 GetEnumIntegerType(self, schema):
318 offset_begin = len(self.int_enums)
Joao da Silva 2014/01/16 10:56:34 Add a check at the beginning: assert all(type(x
Joao da Silva 2014/01/16 10:56:34 You had a nice idea about converting enums into ra
binjin 2014/01/17 14:29:01 Done.
binjin 2014/01/17 14:29:01 Done.
319 self.int_enums += schema['enum']
320 offset_end = len(self.int_enums)
321 return self.AppendSchema('TYPE_INTEGER',
322 self.AppendRestriction(offset_begin, offset_end),
323 'integer with enumeration restriction')
Joao da Silva 2014/01/16 10:56:34 Use "name" (from Generate()) for the 3rd argument
binjin 2014/01/17 14:29:01 Done.
324
325 def GetEnumStringType(self, schema):
326 offset_begin = len(self.string_enums)
Joao da Silva 2014/01/16 10:56:34 Add a check at the beginning: assert all(type(x
binjin 2014/01/17 14:29:01 Done.
327 self.string_enums += schema['enum']
328 offset_end = len(self.string_enums)
329 return self.AppendSchema('TYPE_STRING',
330 self.AppendRestriction(offset_begin, offset_end),
331 'string with enumeration restriction')
Joao da Silva 2014/01/16 10:56:34 Use "name" from Generate() for the 3rd argument
binjin 2014/01/17 14:29:01 Done.
332
333 def GetEnumType(self, schema):
334 if len(schema['enum']) == 0:
335 raise RuntiemError('Empty enumeration in %s' % schema['name'])
Joao da Silva 2014/01/16 10:56:34 RuntimeError schema['name'] does not exist; you h
binjin 2014/01/17 14:29:01 Done.
336 elif schema['type'] == 'integer':
337 return self.GetEnumIntegerType(schema)
338 elif schema['type'] == 'string':
339 return self.GetEnumStringType(schema)
340 else:
341 raise RuntimeError('Unknown enumeration type in %s' % schema['name'])
Joao da Silva 2014/01/16 10:56:34 schema['name'] does not exist
binjin 2014/01/17 14:29:01 Done.
342
343 def GetRangedType(self, schema):
344 if schema['type'] != 'integer':
345 raise RuntimeError('Unknown ranged type in %s' % schema['name'])
Joao da Silva 2014/01/16 10:56:34 schema['name' does not exist; pass "name" from Gen
binjin 2014/01/17 14:29:01 Done.
346 min_value_set, max_value_set = False, False
347 if 'minimum' in schema:
348 min_value = int(schema['minimum'])
349 min_value_set = True
350 if 'maximum' in schema:
351 max_value = int(schema['minimum'])
352 max_value_set = True
353 if min_value_set and max_value_set and min_value > max_value:
354 raise RuntimeError('Invalid ranged type in %s' % schema['name'])
Joao da Silva 2014/01/16 10:56:34 schema['name'] does not exist
binjin 2014/01/17 14:29:01 Done.
355 index = self.AppendRestriction(
356 str(max_value) if max_value_set else 'INT_MAX',
357 str(min_value) if min_value_set else 'INT_MIN')
358 return self.AppendSchema('TYPE_INTEGER',
359 index,
360 'integer with ranged restriction')
Joao da Silva 2014/01/16 10:56:34 Use "name" for the 3rd argument
binjin 2014/01/17 14:29:01 Done.
361
307 def Generate(self, schema, name): 362 def Generate(self, schema, name):
308 """Generates the structs for the given schema. 363 """Generates the structs for the given schema.
309 364
310 |schema|: a valid JSON schema in a dictionary. 365 |schema|: a valid JSON schema in a dictionary.
311 |name|: the name of the current node, for the generated comments.""" 366 |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: 367 if schema['type'] in self.simple_types:
314 return self.GetSimpleType(schema['type']) 368 if not self.SchemaHaveRestriction(schema):
369 # Simple types use shared nodes.
370 return self.GetSimpleType(schema['type'])
371 elif 'enum' in schema:
372 return self.GetEnumType(schema)
373 else:
374 return self.GetRangedType(schema)
315 375
316 if schema['type'] == 'array': 376 if schema['type'] == 'array':
317 # Special case for lists of strings, which is a common policy type. 377 # Special case for lists of strings, which is a common policy type.
318 if schema['items']['type'] == 'string': 378 if schema['items']['type'] == 'string':
319 return self.GetStringList() 379 return self.GetStringList()
320 return self.AppendSchema( 380 return self.AppendSchema(
321 'TYPE_LIST', 381 'TYPE_LIST',
322 self.Generate(schema['items'], 'items of ' + name)) 382 self.Generate(schema['items'], 'items of ' + name))
323 elif schema['type'] == 'object': 383 elif schema['type'] == 'object':
324 # Reserve an index first, so that dictionaries come before their 384 # Reserve an index first, so that dictionaries come before their
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 key += ',' 433 key += ','
374 f.write(' { %-50s %7d },\n' % (key, schema)) 434 f.write(' { %-50s %7d },\n' % (key, schema))
375 f.write('};\n\n') 435 f.write('};\n\n')
376 436
377 f.write('const internal::PropertiesNode kProperties[] = {\n' 437 f.write('const internal::PropertiesNode kProperties[] = {\n'
378 '// Begin End Additional Properties\n') 438 '// Begin End Additional Properties\n')
379 for node in self.properties_nodes: 439 for node in self.properties_nodes:
380 f.write(' { %5d, %5d, %5d }, // %s\n' % node) 440 f.write(' { %5d, %5d, %5d }, // %s\n' % node)
381 f.write('};\n\n') 441 f.write('};\n\n')
382 442
443 f.write('const internal::RestrictionNode kRestrictionNodes[] = {\n')
444 for first, second in self.restriction_nodes:
445 f.write('{{%s,%s}},\n' % (first, second))
Joao da Silva 2014/01/16 10:56:34 Use spacing and a header comment like the arrays a
binjin 2014/01/17 14:29:01 Done.
446 f.write('};\n\n')
447
448 f.write('const int kIntegerEnumerations[] = {\n')
449 for possible_values in self.int_enums:
450 f.write('%d,\n' % possible_values)
Joao da Silva 2014/01/16 10:56:34 Indent with 2 spaces
binjin 2014/01/17 14:29:01 Done.
451 f.write('};\n\n')
452
453 f.write('const char* kStringEnumerations[] = {\n')
454 for possible_values in self.string_enums:
455 f.write('%s\n' % self.GetString(possible_values))
Joao da Silva 2014/01/16 10:56:34 Indent with 2 spaces
binjin 2014/01/17 14:29:01 Done.
456 f.write('};\n\n')
457
383 f.write('const internal::SchemaData kChromeSchemaData = {\n' 458 f.write('const internal::SchemaData kChromeSchemaData = {\n'
384 ' kSchemas,\n' 459 ' kSchemas,\n'
385 ' kPropertyNodes,\n' 460 ' kPropertyNodes,\n'
386 ' kProperties,\n' 461 ' kProperties,\n'
462 ' kRestrictionNodes,\n'
463 ' kIntegerEnumerations,\n'
464 ' kStringEnumerations,\n'
Joao da Silva 2014/01/16 10:56:34 Compilation fails when an array is empty. So if an
binjin 2014/01/17 14:29:01 Done.
387 '};\n\n') 465 '};\n\n')
388 466
389 467
390 def _WritePolicyConstantSource(policies, os, f): 468 def _WritePolicyConstantSource(policies, os, f):
391 f.write('#include "policy/policy_constants.h"\n' 469 f.write('#include "policy/policy_constants.h"\n'
392 '\n' 470 '\n'
393 '#include <algorithm>\n' 471 '#include <algorithm>\n'
472 '#include <climits>\n'
394 '\n' 473 '\n'
395 '#include "base/logging.h"\n' 474 '#include "base/logging.h"\n'
396 '#include "components/policy/core/common/schema_internal.h"\n' 475 '#include "components/policy/core/common/schema_internal.h"\n'
397 '\n' 476 '\n'
398 'namespace policy {\n' 477 'namespace policy {\n'
399 '\n' 478 '\n'
400 'namespace {\n' 479 'namespace {\n'
401 '\n') 480 '\n')
402 481
403 # Generate the Chrome schema. 482 # Generate the Chrome schema.
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 def _WriteCloudPolicyDecoder(policies, os, f): 818 def _WriteCloudPolicyDecoder(policies, os, f):
740 f.write(CPP_HEAD) 819 f.write(CPP_HEAD)
741 for policy in policies: 820 for policy in policies:
742 if policy.is_supported and not policy.is_device_only: 821 if policy.is_supported and not policy.is_device_only:
743 _WritePolicyCode(f, policy) 822 _WritePolicyCode(f, policy)
744 f.write(CPP_FOOT) 823 f.write(CPP_FOOT)
745 824
746 825
747 if __name__ == '__main__': 826 if __name__ == '__main__':
748 sys.exit(main()) 827 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698