summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authordanno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-13 13:26:59 +0000
committerdanno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-13 13:26:59 +0000
commit0e6fd884e68670a70a857d092b79fb7e71bf3856 (patch)
treef4203b7ebbf80f50c52780743692a958b68e4b96 /tools
parent8fbdbc5938f060c003f6d261e4f31ab2d8bf1a98 (diff)
downloadchromium_src-0e6fd884e68670a70a857d092b79fb7e71bf3856.zip
chromium_src-0e6fd884e68670a70a857d092b79fb7e71bf3856.tar.gz
chromium_src-0e6fd884e68670a70a857d092b79fb7e71bf3856.tar.bz2
Auto-generate ADM files
This is the first iteration of my work on the policy MCX/ADM/ADMX/HTML generator. I added chrome/app/policy/policy_templates.grd and a grit extension that parses this file and chrome/app/policy/policy_templates.json and then generates the en-US version of chrome.adm from them. The infrastructure is already in place for other languages and output formats. BUG=49316 TEST=policy_template_generator_unittest.py and manual tests of chrome.adm Review URL: http://codereview.chromium.org/3068012 Patch from Gabor Feher <gfeher@google.com>. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56019 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools')
-rw-r--r--tools/grit/grit/format/policy_templates/__init__.py9
-rw-r--r--tools/grit/grit/format/policy_templates/policy_template_generator.py116
-rw-r--r--tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py220
-rw-r--r--tools/grit/grit/format/policy_templates/template_formatter.py130
-rw-r--r--tools/grit/grit/format/policy_templates/writers/__init__.py9
-rw-r--r--tools/grit/grit/format/policy_templates/writers/adm_writer.py119
-rw-r--r--tools/grit/grit/format/policy_templates/writers/mock_writer.py38
-rw-r--r--tools/grit/grit/format/policy_templates/writers/template_writer.py71
-rw-r--r--tools/grit/grit/gather/json_loader.py53
-rw-r--r--tools/grit/grit/node/misc.py3
-rw-r--r--tools/grit/grit/node/structure.py3
-rw-r--r--tools/grit/grit/test_suite_all.py2
-rw-r--r--tools/grit/grit/tool/build.py1
-rw-r--r--tools/grit/resource_ids7
14 files changed, 780 insertions, 1 deletions
diff --git a/tools/grit/grit/format/policy_templates/__init__.py b/tools/grit/grit/format/policy_templates/__init__.py
new file mode 100644
index 0000000..1f159c0
--- /dev/null
+++ b/tools/grit/grit/format/policy_templates/__init__.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Module grit.format.policy_templates
+'''
+
+pass
+
diff --git a/tools/grit/grit/format/policy_templates/policy_template_generator.py b/tools/grit/grit/format/policy_templates/policy_template_generator.py
new file mode 100644
index 0000000..efbf769
--- /dev/null
+++ b/tools/grit/grit/format/policy_templates/policy_template_generator.py
@@ -0,0 +1,116 @@
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+class PolicyTemplateGenerator:
+ '''Generates template text for a particular platform.
+
+ This class is used to traverse a JSON structure from a .json template
+ definition metafile and merge GUI message string definitions that come
+ from a .grd resource tree onto it. After this, it can be used to output
+ this data to policy template files using TemplateWriter objects.
+ '''
+
+ def __init__(self, messages, policy_groups):
+ '''Initializes this object with all the data necessary to output a
+ policy template.
+
+ Args:
+ messages: An identifier to string dictionary of all the localized
+ messages that might appear in the policy template.
+ policy_groups: The policies are organized into groups, and each policy
+ has a name and type. The user will see a GUI interface for assigning
+ values to policies, by using the templates generated here. The traversed
+ data structure is a dictionary of policy group names to groups. Each
+ group is a dictionary and has an embedded dictionary of policies under
+ the key 'policies'. Example:
+ policy_groups = {
+ 'PolicyGroup1': {
+ 'policies': {
+ 'Policy1Name': {'type': 'string'}
+ 'Policy2Name': {'type': 'main'}
+ 'Policy3Name': {'type': 'enum', 'items': {...}}
+ }
+ },
+ 'PolicyGroup2': {...}
+ }
+ See chrome/app/policy.policy_templates.json for an example and more
+ details.
+ '''
+ # List of all the policies:
+ self._policy_groups = policy_groups
+ # Localized messages to be inserted to the policy_groups structure:
+ self._messages = messages
+ self._AddMessagesToPolicies()
+
+ def _AddMessagesToItem(self, item_name, item, warn_no_desc):
+ '''Adds localized message strings to an item of the policy data structure
+ (self._policy_groups).
+
+ Args:
+ item_name: The name of the item.
+ item: The item which will get its message strings now.
+ warn_no_desc: A boolean value. If it is True, warnings will be
+ printed in case there are no description strings for item in
+ self._messages.
+ '''
+ # The keys for the item's messages in self._messages:
+ caption_id = 'IDS_POLICY_%s_CAPTION' % item_name
+ desc_id = 'IDS_POLICY_%s_DESC' % item_name
+ # Copy the messages from self._messages to item:
+ if caption_id in self._messages:
+ item['caption'] = self._messages[caption_id]
+ else:
+ print 'Warning: no localized message for ' + caption_id
+ if desc_id in self._messages:
+ item['desc'] = self._messages[desc_id]
+ elif warn_no_desc:
+ print 'Warning: no localized message for ' + desc_id
+
+ def _AddMessagesToPolicies(self):
+ '''Adds localized message strings to each item of the policy data structure
+ (self._policy_groups).
+ '''
+ # Iterate through all the policy groups.
+ for group_name, group in self._policy_groups.iteritems():
+ # Get caption and description for this group.
+ group_name = 'GROUP_' + group_name.upper()
+ self._AddMessagesToItem(group_name, group, True)
+ if 'policies' in group:
+ # Iterate through all the policies in the current group.
+ for policy_name, policy in group['policies'].iteritems():
+ if policy['type'] == 'enum':
+ # Iterate through all the items of an enum-type policy.
+ for item_name, item in policy['items'].iteritems():
+ self._AddMessagesToItem('ENUM_' + item_name.upper(), item, False)
+ elif policy['type'] == 'main':
+ # In this case, messages are inherited from the group.
+ policy['caption'] = group['caption']
+ policy['desc'] = group['desc']
+ continue
+ # Get caption for this policy.
+ full_name = policy_name.upper()
+ self._AddMessagesToItem(full_name, policy, False)
+
+ def GetTemplateText(self, template_writer):
+ '''Generates the text of the template from the arguments given
+ to the constructor, using a given TemplateWriter.
+
+ Args:
+ template_writer: An object implementing TemplateWriter. Its methods
+ are called here for each item of self._policy_groups.
+
+ Returns:
+ The text of the generated template.
+ '''
+ template_writer.Prepare()
+ template_writer.BeginTemplate()
+ for group_name, group in self._policy_groups.iteritems():
+ template_writer.BeginPolicyGroup(group_name, group)
+ if 'policies' in group:
+ for policy_name, policy in group['policies'].iteritems():
+ template_writer.WritePolicy(policy_name, policy)
+ template_writer.EndPolicyGroup()
+ template_writer.EndTemplate()
+ return template_writer.GetTemplateText()
diff --git a/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py b/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py
new file mode 100644
index 0000000..7f5923b9
--- /dev/null
+++ b/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py
@@ -0,0 +1,220 @@
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+import unittest
+
+from policy_template_generator import PolicyTemplateGenerator
+from writers.mock_writer import MockWriter
+
+
+class PolicyTemplateGeneratorUnittest(unittest.TestCase):
+ '''Unit tests for policy_template_generator.py.'''
+
+ def do_test(self, strings, policy_groups, writer):
+ '''Executes a test case.
+
+ Creates and invokes an instance of PolicyTemplateGenerator with
+ the given arguments.
+
+ Notice: Plain comments are used in test methods instead of docstrings,
+ so that method names do not get overridden by the docstrings in the
+ test output.
+
+ Args:
+ strings: The dictionary of localized strings.
+ policy_groups: The list of policy groups as it would be loaded from
+ policy_templates.json.
+ writer: A writer used for this test. It is usually derived from
+ mock_writer.MockWriter.
+ '''
+ writer.tester = self
+ policy_generator = PolicyTemplateGenerator(strings, policy_groups)
+ res = policy_generator.GetTemplateText(writer)
+ writer.Test()
+ return res
+
+ def testSequence(self):
+ # Test the sequence of invoking the basic PolicyWriter operations,
+ # in case of empty input data structures.
+ class LocalMockWriter(MockWriter):
+ def __init__(self):
+ self.log = 'init;'
+ def Prepare(self):
+ self.log += 'prepare;'
+ def BeginTemplate(self):
+ self.log += 'begin;'
+ def EndTemplate(self):
+ self.log += 'end;'
+ def GetTemplateText(self):
+ self.log += 'get_text;'
+ return 'writer_result_string'
+ def Test(self):
+ self.tester.assertEquals(self.log,
+ 'init;prepare;begin;end;get_text;')
+ result = self.do_test({}, {}, LocalMockWriter())
+ self.assertEquals(result, 'writer_result_string')
+
+ def testEmptyGroups(self):
+ # Test that in case of three empty policy groups, each one is passed to
+ # the writer.
+ strings_mock = {
+ 'IDS_POLICY_GROUP_GROUP1_CAPTION': None,
+ 'IDS_POLICY_GROUP_GROUP1_DESC': None,
+ 'IDS_POLICY_GROUP_GROUP2_CAPTION': None,
+ 'IDS_POLICY_GROUP_GROUP2_DESC': None,
+ 'IDS_POLICY_GROUP_GROUP3_CAPTION': None,
+ 'IDS_POLICY_GROUP_GROUP3_DESC': None,
+ }
+ policies_mock = {
+ 'Group1': {'tag': 'T1'},
+ 'Group2': {'tag': 'T2'},
+ 'Group3': {'tag': 'T3'},
+ }
+ class LocalMockWriter(MockWriter):
+ def __init__(self):
+ self.log = ''
+ self.set = set()
+ def BeginPolicyGroup(self, group_name, group):
+ self.log += '['
+ self.set.add ( (group_name, group['tag']) )
+ def EndPolicyGroup(self):
+ self.log += ']'
+ def Test(self):
+ self.tester.assertEquals(self.log, '[][][]')
+ self.tester.assertEquals(
+ self.set,
+ set([('Group1', 'T1'), ('Group2', 'T2'), ('Group3', 'T3')]))
+ self.do_test(strings_mock, policies_mock, LocalMockWriter())
+
+ def testGroupTexts(self):
+ # Test that GUI strings are assigned correctly to policy groups.
+ strings_mock = {
+ 'IDS_POLICY_GROUP_GROUP1_CAPTION': 'string1',
+ 'IDS_POLICY_GROUP_GROUP1_DESC': 'string2',
+ 'IDS_POLICY_GROUP_GROUP2_CAPTION': 'string3',
+ 'IDS_POLICY_GROUP_GROUP2_DESC': 'string4',
+ }
+ policies_mock = {
+ 'Group1': {},
+ 'Group2': {},
+ }
+ class LocalMockWriter(MockWriter):
+ def BeginPolicyGroup(self, group_name, group):
+ if group_name == 'Group1':
+ self.tester.assertEquals(group['caption'], 'string1')
+ self.tester.assertEquals(group['desc'], 'string2')
+ elif group_name == 'Group2':
+ self.tester.assertEquals(group['caption'], 'string3')
+ self.tester.assertEquals(group['desc'], 'string4')
+ else:
+ self.tester.fail()
+ self.do_test(strings_mock, policies_mock, LocalMockWriter())
+
+ def testPolicies(self):
+ # Test that policies are passed correctly to the writer.
+ strings_mock = {
+ 'IDS_POLICY_GROUP_GROUP1_CAPTION': None,
+ 'IDS_POLICY_GROUP_GROUP1_DESC': None,
+ 'IDS_POLICY_GROUP_GROUP2_CAPTION': None,
+ 'IDS_POLICY_GROUP_GROUP2_DESC': None,
+ 'IDS_POLICY_GROUP1POLICY1_CAPTION': None,
+ 'IDS_POLICY_GROUP1POLICY2_CAPTION': None,
+ 'IDS_POLICY_GROUP2POLICY3_CAPTION': None,
+ }
+ policies_mock = {
+ 'Group1': {
+ 'policies': {
+ 'Group1Policy1': {'type': 'string'},
+ 'Group1Policy2': {'type': 'string'}
+ }
+ },
+ 'Group2': {
+ 'policies': {
+ 'Group2Policy3': {'type': 'string'}
+ }
+ }
+ }
+ class LocalMockWriter(MockWriter):
+ def __init__(self):
+ self.policy_name = None
+ self.policy_set = set()
+ def BeginPolicyGroup(self, group_name, group):
+ self.group_name = group_name
+ def EndPolicyGroup(self):
+ self.group_name = None
+ def WritePolicy(self, group_name, group):
+ self.tester.assertEquals(group_name[0:6], self.group_name)
+ self.policy_set.add(group_name)
+ def Test(self):
+ self.tester.assertEquals(
+ self.policy_set,
+ set(['Group1Policy1', 'Group1Policy2', 'Group2Policy3']))
+ self.do_test(strings_mock, policies_mock, LocalMockWriter())
+
+ def testPolicyTexts(self):
+ # Test that GUI strings are assigned correctly to policies.
+ strings_mock = {
+ 'IDS_POLICY_POLICY1_CAPTION': 'string1',
+ 'IDS_POLICY_POLICY1_DESC': 'string2',
+ 'IDS_POLICY_POLICY2_CAPTION': 'string3',
+ 'IDS_POLICY_POLICY2_DESC': 'string4',
+ 'IDS_POLICY_GROUP_GROUP1_CAPTION': None,
+ 'IDS_POLICY_GROUP_GROUP1_DESC': None,
+ }
+ policies_mock = {
+ 'Group1': {
+ 'policies': {
+ 'Policy1': {'type': 'string'},
+ 'Policy2': {'type': 'string'}
+ }
+ }
+ }
+ class LocalMockWriter(MockWriter):
+ def WritePolicy(self, policy_name, policy):
+ if policy_name == 'Policy1':
+ self.tester.assertEquals(policy['caption'], 'string1')
+ self.tester.assertEquals(policy['desc'], 'string2')
+ elif policy_name == 'Policy2':
+ self.tester.assertEquals(policy['caption'], 'string3')
+ self.tester.assertEquals(policy['desc'], 'string4')
+ else:
+ self.tester.fail()
+ self.do_test(strings_mock, policies_mock, LocalMockWriter())
+
+ def testEnumTexts(self):
+ # Test that GUI strings are assigned correctly to enums
+ # (aka dropdown menus).
+ strings_mock = {
+ 'IDS_POLICY_ENUM_ITEM1_CAPTION': 'string1',
+ 'IDS_POLICY_ENUM_ITEM2_CAPTION': 'string2',
+ 'IDS_POLICY_ENUM_ITEM3_CAPTION': 'string3',
+ 'IDS_POLICY_POLICY1_CAPTION': None,
+ 'IDS_POLICY_GROUP_GROUP1_CAPTION': None,
+ 'IDS_POLICY_GROUP_GROUP1_DESC': None,
+ }
+ policies_mock = {
+ 'Group1': {
+ 'policies': {
+ 'Policy1': {
+ 'type': 'enum',
+ 'items': {
+ 'item1': {'value': '0'},
+ 'item2': {'value': '1'},
+ 'item3': {'value': '3'},
+ }
+ }
+ }
+ }
+ }
+ class LocalMockWriter(MockWriter):
+ def WritePolicy(self, policy_name, policy):
+ self.tester.assertEquals(policy['items']['item1']['caption'], 'string1')
+ self.tester.assertEquals(policy['items']['item2']['caption'], 'string2')
+ self.tester.assertEquals(policy['items']['item3']['caption'], 'string3')
+ self.do_test(strings_mock, policies_mock, LocalMockWriter())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tools/grit/grit/format/policy_templates/template_formatter.py b/tools/grit/grit/format/policy_templates/template_formatter.py
new file mode 100644
index 0000000..47fd474
--- /dev/null
+++ b/tools/grit/grit/format/policy_templates/template_formatter.py
@@ -0,0 +1,130 @@
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+from grit.format import interface
+from grit.node import structure
+from grit.node import message
+from grit.node import misc
+from policy_template_generator import PolicyTemplateGenerator
+import types
+import os
+import sys
+
+
+class TemplateFormatter(interface.ItemFormatter):
+ '''Creates a template file corresponding to an <output> node of the grit
+ tree.
+
+ More precisely, processes the whole grit tree for a given <output> node whose
+ type is 'adm'. TODO(gfeher) add new types here
+ The result of processing is a policy template file with the
+ given type and language of the <output> node. A new instance of this class
+ is created by grit.misc.GritNode for each <output> node. This class does
+ the interfacing with grit, but the actual template-generating work is done in
+ policy_template_generator.PolicyTemplateGenerator.
+ '''
+
+ def __init__(self, writer_name):
+ '''Initializes this formatter to output messages with a given writer.
+
+ Args:
+ writer_name: A string identifying the TemplateWriter subclass used
+ for generating the output. If writer name is 'adm', then the class
+ from module 'writers.adm_writer' will be used.
+ '''
+ super(type(self), self).__init__()
+ writer_module_name = \
+ 'grit.format.policy_templates.writers.' + writer_name + '_writer'
+ __import__(writer_module_name)
+ # The module that contains the writer class:
+ self._writer_module = sys.modules[writer_module_name]
+
+ def Format(self, item, lang='en', begin_item=True, output_dir='.'):
+ '''Generates a template corresponding to an <output> node in the grd file.
+
+ Args:
+ item: the <grit> root node of the grit tree.
+ lang: the language of outputted text, e.g.: 'en'
+ begin_item: True or False, depending on if this function was called at
+ the beginning or at the end of the item.
+ output_dir: The output directory, currently unused here.
+
+ Returns:
+ The text of the template file.
+ '''
+ if not begin_item:
+ return ''
+
+ self._lang = lang
+ self._SetBranding(item)
+ self._policy_groups = None
+ self._messages = {}
+ self._ParseGritNodes(item)
+ return self._GetOutput()
+
+ def _GetOutput(self):
+ '''Generates a template file using the instance variables initialized
+ in Format() using the writer specified in __init__().
+
+ Returns:
+ The text of the policy template based on the parameters passed
+ to __init__() and Format().
+ '''
+ policy_generator = \
+ PolicyTemplateGenerator(self._messages, self._policy_groups)
+ writer = self._writer_module.GetWriter(self._build)
+ str = policy_generator.GetTemplateText(writer)
+ return str
+
+ def _SetBranding(self, item):
+ '''Sets self._branding and self._build based on the -D_chromium or
+ -D_google_chrome command line switch of grit.
+
+ Args:
+ item: The <grit> root node of the grit tree.
+ '''
+ defines = item.defines
+ if '_chromium' in defines:
+ self._branding = 'Chromium'
+ self._build = 'chromium'
+ elif '_google_chrome' in defines:
+ self._branding = 'Google Chrome'
+ self._build = 'chrome'
+ else:
+ raise Exception('Unknown build')
+
+ def _ImportMessage(self, message):
+ '''Takes a grit message node and adds its translated content to
+ self._messages.
+
+ Args:
+ message: A <message> node in the grit tree.
+ '''
+ msg_name = message.GetTextualIds()[0]
+ msg_txt = message.Translate(self._lang)
+ msg_txt = msg_txt.replace('$1', self._branding)
+ lines = msg_txt.split('\n')
+ lines = [line.strip() for line in lines]
+ msg_txt = "\\n".join(lines)
+ self._messages[msg_name] = msg_txt
+
+ def _ParseGritNodes(self, item):
+ '''Collects the necessary information from the grit tree:
+ the message strings and the policy definitions.
+
+ Args:
+ item: The grit node parsed currently.
+ '''
+ nodes = []
+ if (isinstance(item, misc.IfNode) and not item.IsConditionSatisfied()):
+ return
+ if (isinstance(item, structure.StructureNode) and
+ item.attrs['type'] == 'policy_template_metafile'):
+ assert self._policy_groups == None
+ self._policy_groups = item.gatherer.GetData()
+ elif (isinstance(item, message.MessageNode)):
+ self._ImportMessage(item)
+ for child in item.children:
+ self._ParseGritNodes(child)
diff --git a/tools/grit/grit/format/policy_templates/writers/__init__.py b/tools/grit/grit/format/policy_templates/writers/__init__.py
new file mode 100644
index 0000000..68aab64
--- /dev/null
+++ b/tools/grit/grit/format/policy_templates/writers/__init__.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Module grit.format.policy_templates.writers
+'''
+
+pass
+
diff --git a/tools/grit/grit/format/policy_templates/writers/adm_writer.py b/tools/grit/grit/format/policy_templates/writers/adm_writer.py
new file mode 100644
index 0000000..e7b7c36
--- /dev/null
+++ b/tools/grit/grit/format/policy_templates/writers/adm_writer.py
@@ -0,0 +1,119 @@
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+from template_writer import TemplateWriter
+
+
+def GetWriter(build):
+ return AdmWriter(build)
+
+
+class AdmWriter(TemplateWriter):
+ '''Class for generating policy templates in Windows ADM format.
+ It is used by PolicyTemplateGenerator to write ADM files.
+ '''
+
+ TYPE_TO_INPUT = {
+ 'string': 'EDITTEXT',
+ 'enum': 'DROPDOWNLIST'}
+ NEWLINE = '\r\n'
+
+ def _AddGuiString(self, name, value):
+ line = '%s="%s"' % (name, value)
+ self.str_list.append(line)
+
+ def _PrintLine(self, string='', indent_diff=0):
+ '''Prints a string with indents and a linebreak to the output.
+
+ Args:
+ string: The string to print.
+ indent_diff: the difference of indentation of the printed line,
+ compared to the next/previous printed line. Increment occurs
+ after printing the line, while decrement occurs before that.
+ '''
+ indent_diff *= 2
+ if indent_diff < 0:
+ self.indent = self.indent[(-indent_diff):]
+ self.policy_list.append(self.indent + string)
+ if indent_diff > 0:
+ self.indent += ''.ljust(indent_diff)
+
+ def _WriteSupported(self):
+ self._PrintLine('#if version >= 4', 1)
+ self._PrintLine('SUPPORTED !!SUPPORTED_WINXPSP2')
+ self._PrintLine('#endif', -1)
+
+ def WritePolicy(self, policy_name, policy):
+ type = policy['type']
+ if type == 'main':
+ self._PrintLine('VALUENAME "%s"' % policy_name )
+ self._PrintLine('VALUEON NUMERIC 1')
+ self._PrintLine('VALUEOFF NUMERIC 0')
+ return
+
+ policy_part_name = policy_name + '_Part'
+ self._AddGuiString(policy_part_name, policy['caption'])
+
+ self._PrintLine()
+ self._PrintLine(
+ 'PART !!%s %s' % (policy_part_name, self.TYPE_TO_INPUT[type]),
+ 1)
+ self._PrintLine('VALUENAME "%s"' % policy_name)
+ if type == 'enum':
+ self._PrintLine('ITEMLIST', 1)
+ for item_name, item in policy['items'].iteritems():
+ self._PrintLine(
+ 'NAME !!%s_DropDown VALUE NUMERIC %s' % (item_name, item['value']))
+ self._AddGuiString(item_name + '_DropDown', item['caption'])
+ self._PrintLine('END ITEMLIST', -1)
+ self._PrintLine('END PART', -1)
+
+ def BeginPolicyGroup(self, group_name, group):
+ group_explain_name = group_name + '_Explain'
+ self._AddGuiString(group_name + '_Policy', group['caption'])
+ self._AddGuiString(group_explain_name, group['desc'])
+
+ self._PrintLine('POLICY !!%s_Policy' % group_name, 1)
+ self._WriteSupported()
+ self._PrintLine('EXPLAIN !!' + group_explain_name)
+
+ def EndPolicyGroup(self):
+ self._PrintLine('END POLICY', -1)
+ self._PrintLine()
+
+ def BeginTemplate(self):
+ # TODO(gfeher): Move this string to .grd.
+ self._AddGuiString('SUPPORTED_WINXPSP2',
+ 'At least Microsoft Windows XP SP2')
+ self._PrintLine('CLASS MACHINE', 1)
+ if self.build == 'chrome':
+ self._AddGuiString('google', 'Google')
+ self._AddGuiString('googlechrome', 'Google Chrome')
+ self._PrintLine('CATEGORY !!google', 1)
+ self._PrintLine('CATEGORY !!googlechrome', 1)
+ self._PrintLine('KEYNAME "Software\\Policies\\Google\\Google Chrome"')
+ elif self.build == 'chromium':
+ self._AddGuiString('chromium', 'Chromium')
+ self._PrintLine('CATEGORY !!chromium', 1)
+ self._PrintLine('KEYNAME "Software\\Policies\\Chromium"')
+ self._PrintLine()
+
+ def EndTemplate(self):
+ if self.build == 'chrome':
+ self._PrintLine('END CATEGORY', -1)
+ self._PrintLine('END CATEGORY', -1)
+ self._PrintLine('', -1)
+ elif self.build == 'chromium':
+ self._PrintLine('END CATEGORY', -1)
+ self._PrintLine('', -1)
+
+ def Prepare(self):
+ self.policy_list = []
+ self.str_list = ['[Strings]']
+ self.indent = ''
+
+ def GetTemplateText(self):
+ lines = self.policy_list + self.str_list
+ return self.NEWLINE.join(lines)
diff --git a/tools/grit/grit/format/policy_templates/writers/mock_writer.py b/tools/grit/grit/format/policy_templates/writers/mock_writer.py
new file mode 100644
index 0000000..8700b68
--- /dev/null
+++ b/tools/grit/grit/format/policy_templates/writers/mock_writer.py
@@ -0,0 +1,38 @@
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+from template_writer import TemplateWriter
+
+
+class MockWriter(TemplateWriter):
+ '''Helper class for unit tests in policy_template_generator_unittest.py
+ '''
+
+ def __init__(self):
+ pass
+
+ def WritePolicy(self, policy_name, policy):
+ pass
+
+ def BeginPolicyGroup(self, group_name, group):
+ pass
+
+ def EndPolicyGroup(self):
+ pass
+
+ def BeginTemplate(self):
+ pass
+
+ def EndTemplate(self):
+ pass
+
+ def Prepare(self):
+ pass
+
+ def GetTemplateText(self):
+ pass
+
+ def Test(self):
+ pass
diff --git a/tools/grit/grit/format/policy_templates/writers/template_writer.py b/tools/grit/grit/format/policy_templates/writers/template_writer.py
new file mode 100644
index 0000000..cb80fb2
--- /dev/null
+++ b/tools/grit/grit/format/policy_templates/writers/template_writer.py
@@ -0,0 +1,71 @@
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+class TemplateWriter(object):
+ '''Abstract base class for writing policy templates in various formats.
+ The methods of this class will be called by PolicyTemplateGenerator.
+ '''
+
+ def __init__(self, build):
+ '''Initializes a TemplateWriter object.
+
+ Args:
+ build: 'chrome' or 'chromium'
+ '''
+ assert build in ['chrome', 'chromium']
+ self.build = build
+
+ def Prepare(self):
+ '''Initializes the internal buffer where the template will be
+ stored.
+ '''
+ raise NotImplementedError()
+
+ def WritePolicy(self, policy_name, policy):
+ '''Appends the template text corresponding to a policy into the
+ internal buffer.
+
+ Args:
+ policy_name: The name of the policy that has to be written.
+ policy: The policy as it is found in the JSON file.
+ '''
+ raise NotImplementedError()
+
+ def BeginPolicyGroup(self, group_name, group):
+ '''Appends the template text corresponding to the beginning of a
+ policy group into the internal buffer.
+
+ Args:
+ group_name: The name of the policy group that has to be written.
+ group: The policy group as it is found in the JSON file.
+ '''
+ raise NotImplementedError()
+
+ def EndPolicyGroup(self):
+ '''Appends the template text corresponding to the end of a
+ policy group into the internal buffer.
+ '''
+ raise NotImplementedError()
+
+ def BeginTemplate(self):
+ '''Appends the text corresponding to the beginning of the whole
+ template into the internal buffer.
+ '''
+ raise NotImplementedError()
+
+ def EndTemplate(self):
+ '''Appends the text corresponding to the end of the whole
+ template into the internal buffer.
+ '''
+ raise NotImplementedError()
+
+
+ def GetTemplateText(self):
+ '''Gets the content of the internal template buffer.
+
+ Returns:
+ The generated template from the the internal buffer as a string.
+ '''
+ raise NotImplementedError()
diff --git a/tools/grit/grit/gather/json_loader.py b/tools/grit/grit/gather/json_loader.py
new file mode 100644
index 0000000..e2518e4
--- /dev/null
+++ b/tools/grit/grit/gather/json_loader.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+import types
+
+from grit.gather import interface
+from grit import util
+
+
+class JsonLoader(interface.GathererBase):
+ '''A simple gatherer that loads and parses a JSON file.'''
+
+ def __init__(self, json_text):
+ '''Initializes a gatherer object with JSON input.
+
+ Args:
+ json_text: A string containing a JSON expression.
+ '''
+ super(type(self), self).__init__()
+ self._json_text = json_text
+ self._data = None
+
+ def Parse(self):
+ '''Parses the text of self._json_text into the data structure in
+ self._data.
+ '''
+ globs = {}
+ exec('data = ' + self._json_text, globs)
+ self._data = globs['data']
+
+ def GetData(self):
+ '''Returns the parsed JSON data.'''
+ return self._data
+
+ def FromFile(filename_or_stream, extkey, encoding):
+ '''Creates a JSONLoader instance from a file or stream.
+
+ Args:
+ filename_or_stream: The source of JSON data.
+ extkey: Unused, see interface.py.
+ encoding: The encoding used in the JSON file. (Note that it should
+ not contain localized strings.)
+
+ Returns:
+ The JSONLoader instance holding the JSON data unparsed.
+ '''
+ if isinstance(filename_or_stream, types.StringTypes):
+ filename_or_stream = \
+ util.WrapInputStream(file(filename_or_stream, 'rU'), encoding)
+ return JsonLoader(filename_or_stream.read())
+ FromFile = staticmethod(FromFile)
diff --git a/tools/grit/grit/node/misc.py b/tools/grit/grit/node/misc.py
index 6ede0c6..56fec47 100644
--- a/tools/grit/grit/node/misc.py
+++ b/tools/grit/grit/node/misc.py
@@ -228,6 +228,9 @@ class GritNode(base.Node):
elif t == 'js_map_format':
from grit.format import js_map_format
return js_map_format.TopLevel()
+ elif t == 'adm':
+ from grit.format.policy_templates import template_formatter
+ return template_formatter.TemplateFormatter(t)
else:
return super(type(self), self).ItemFormatter(t)
diff --git a/tools/grit/grit/node/structure.py b/tools/grit/grit/node/structure.py
index 7058cd3..95eac76 100644
--- a/tools/grit/grit/node/structure.py
+++ b/tools/grit/grit/node/structure.py
@@ -15,6 +15,7 @@ from grit import constants
from grit import exception
from grit import util
+import grit.gather.json_loader
import grit.gather.rc
import grit.gather.tr_html
import grit.gather.admin_template
@@ -44,6 +45,7 @@ _GATHERERS = {
'tr_html' : grit.gather.tr_html.TrHtml,
'txt' : grit.gather.txt.TxtFile,
'version' : grit.gather.rc.Version,
+ 'policy_template_metafile' : grit.gather.json_loader.JsonLoader,
}
@@ -59,6 +61,7 @@ _RC_FORMATTERS = {
'tr_html' : grit.format.rc.RcInclude('HTML'),
'txt' : grit.format.rc.RcInclude('TXT'),
'version' : grit.format.rc.RcSection(),
+ 'policy_template_metafile': None,
}
diff --git a/tools/grit/grit/test_suite_all.py b/tools/grit/grit/test_suite_all.py
index cb2d087..98b9d0d 100644
--- a/tools/grit/grit/test_suite_all.py
+++ b/tools/grit/grit/test_suite_all.py
@@ -46,6 +46,7 @@ class TestSuiteAll(unittest.TestSuite):
from grit.gather import muppet_strings_unittest
from grit.node.custom import filename_unittest
import grit.format.js_map_format_unittest
+ from grit.format.policy_templates import policy_template_generator_unittest
test_classes = [
base_unittest.NodeUnittest,
@@ -75,6 +76,7 @@ class TestSuiteAll(unittest.TestSuite):
muppet_strings_unittest.MuppetStringsUnittest,
filename_unittest.WindowsFilenameUnittest,
grit.format.js_map_format_unittest.JsMapFormatUnittest,
+ policy_template_generator_unittest.PolicyTemplateGeneratorUnittest,
# add test classes here...
]
diff --git a/tools/grit/grit/tool/build.py b/tools/grit/grit/tool/build.py
index 0a79769..9d1c6bc1 100644
--- a/tools/grit/grit/tool/build.py
+++ b/tools/grit/grit/tool/build.py
@@ -185,6 +185,7 @@ are exported to translation interchange files (e.g. XMB files), etc.
elif output.GetType() == 'js_map_format':
encoding = 'utf_8'
else:
+ # TODO(gfeher) modify here to set utf-8 encoding for admx/adml
encoding = 'utf_16'
# Make the output directory if it doesn't exist.
diff --git a/tools/grit/resource_ids b/tools/grit/resource_ids
index 93905dd..f33298f 100644
--- a/tools/grit/resource_ids
+++ b/tools/grit/resource_ids
@@ -116,5 +116,10 @@
"gfx/gfx_resources.grd": {
"includes": [18500],
- }
+ },
+
+ "chrome/app/policy/policy_templates.grd": {
+ "structures": [19000],
+ "messages": [19010],
+ },
}