diff options
author | danno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-13 13:26:59 +0000 |
---|---|---|
committer | danno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-13 13:26:59 +0000 |
commit | 0e6fd884e68670a70a857d092b79fb7e71bf3856 (patch) | |
tree | f4203b7ebbf80f50c52780743692a958b68e4b96 /tools | |
parent | 8fbdbc5938f060c003f6d261e4f31ab2d8bf1a98 (diff) | |
download | chromium_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__.py | 9 | ||||
-rw-r--r-- | tools/grit/grit/format/policy_templates/policy_template_generator.py | 116 | ||||
-rw-r--r-- | tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py | 220 | ||||
-rw-r--r-- | tools/grit/grit/format/policy_templates/template_formatter.py | 130 | ||||
-rw-r--r-- | tools/grit/grit/format/policy_templates/writers/__init__.py | 9 | ||||
-rw-r--r-- | tools/grit/grit/format/policy_templates/writers/adm_writer.py | 119 | ||||
-rw-r--r-- | tools/grit/grit/format/policy_templates/writers/mock_writer.py | 38 | ||||
-rw-r--r-- | tools/grit/grit/format/policy_templates/writers/template_writer.py | 71 | ||||
-rw-r--r-- | tools/grit/grit/gather/json_loader.py | 53 | ||||
-rw-r--r-- | tools/grit/grit/node/misc.py | 3 | ||||
-rw-r--r-- | tools/grit/grit/node/structure.py | 3 | ||||
-rw-r--r-- | tools/grit/grit/test_suite_all.py | 2 | ||||
-rw-r--r-- | tools/grit/grit/tool/build.py | 1 | ||||
-rw-r--r-- | tools/grit/resource_ids | 7 |
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], + }, } |