Commit b20c4619 authored by gfeher@chromium.org's avatar gfeher@chromium.org

Allow ADM(X) templates to manage both MACHINE and USER policies

ADMX policies will have the XML attribute class set to "both", ADM policies will be presented twice, once under CLASS MACHINE, and once under CLASS USER.

BUG=70232
TEST=Add chrome.adm to Group Policy Editor and see if Chrome policies appear both under User Configuration and Machine Configuration, and they can be configured independently. Repeat this with chrome.admx.

Review URL: http://codereview.chromium.org/6327011

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72792 0039d316-1c4b-4281-b951-d872f2087c98
parent 6e6f6cb2
......@@ -43,7 +43,7 @@ def GetConfigurationForBuild(defines):
}
else:
raise Exception('Unknown build')
config['win_group_policy_class'] = 'Machine'
config['win_group_policy_class'] = 'both'
config['win_supported_os'] = 'SUPPORTED_WINXPSP2'
if 'mac_bundle_id' in defines:
config['mac_bundle_id'] = defines['mac_bundle_id']
......
......@@ -6,6 +6,9 @@
from grit.format.policy_templates.writers import template_writer
NEWLINE = '\r\n'
def GetWriter(config):
'''Factory method for creating AdmWriter objects.
See the constructor of TemplateWriter for description of
......@@ -14,27 +17,15 @@ def GetWriter(config):
return AdmWriter(['win'], config)
class AdmWriter(template_writer.TemplateWriter):
'''Class for generating policy templates in Windows ADM format.
It is used by PolicyTemplateGenerator to write ADM files.
'''
TYPE_TO_INPUT = {
'string': 'EDITTEXT',
'int': 'NUMERIC',
'string-enum': 'DROPDOWNLIST',
'int-enum': 'DROPDOWNLIST',
'list': 'LISTBOX'}
NEWLINE = '\r\n'
class IndentedStringBuilder:
'''Utility class for building text with indented lines.'''
def _AddGuiString(self, name, value):
# Escape newlines in the value.
value = value.replace('\n', '\\n')
line = '%s="%s"' % (name, value)
self.str_list.append(line)
def __init__(self):
self.lines = []
self.indent = ''
def _PrintLine(self, string='', indent_diff=0):
'''Prints a string with indents and a linebreak to the output.
def AddLine(self, string='', indent_diff=0):
'''Appends a string with indentation and a linebreak to |self.lines|.
Args:
string: The string to print.
......@@ -46,16 +37,51 @@ class AdmWriter(template_writer.TemplateWriter):
if indent_diff < 0:
self.indent = self.indent[(-indent_diff):]
if string != '':
self.policy_list.append(self.indent + string)
self.lines.append(self.indent + string)
else:
self.policy_list.append('')
self.lines.append('')
if indent_diff > 0:
self.indent += ''.ljust(indent_diff)
def AddLines(self, other):
'''Appends the content of another |IndentedStringBuilder| to |self.lines|.
Indentation of the added lines will be the sum of |self.indent| and
their original indentation.
Args:
other: The buffer from which lines are copied.
'''
for line in other.lines:
self.AddLine(line)
def ToString(self):
'''Returns |self.lines| as text string.'''
return NEWLINE.join(self.lines)
class AdmWriter(template_writer.TemplateWriter):
'''Class for generating policy templates in Windows ADM format.
It is used by PolicyTemplateGenerator to write ADM files.
'''
TYPE_TO_INPUT = {
'string': 'EDITTEXT',
'int': 'NUMERIC',
'string-enum': 'DROPDOWNLIST',
'int-enum': 'DROPDOWNLIST',
'list': 'LISTBOX'
}
def _AddGuiString(self, name, value):
# Escape newlines in the value.
value = value.replace('\n', '\\n')
line = '%s="%s"' % (name, value)
self.strings.AddLine(line)
def _WriteSupported(self):
self._PrintLine('#if version >= 4', 1)
self._PrintLine('SUPPORTED !!SUPPORTED_WINXPSP2')
self._PrintLine('#endif', -1)
self.policies.AddLine('#if version >= 4', 1)
self.policies.AddLine('SUPPORTED !!SUPPORTED_WINXPSP2')
self.policies.AddLine('#endif', -1)
def _WritePart(self, policy):
'''Writes the PART ... END PART section of a policy.
......@@ -67,47 +93,47 @@ class AdmWriter(template_writer.TemplateWriter):
self._AddGuiString(policy_part_name, policy['label'])
# Print the PART ... END PART section:
self._PrintLine()
self.policies.AddLine()
adm_type = self.TYPE_TO_INPUT[policy['type']]
self._PrintLine('PART !!%s %s' % (policy_part_name, adm_type), 1)
self.policies.AddLine('PART !!%s %s' % (policy_part_name, adm_type), 1)
if policy['type'] == 'list':
# Note that the following line causes FullArmor ADMX Migrator to create
# corrupt ADMX files. Please use admx_writer to get ADMX files.
self._PrintLine('KEYNAME "%s\\%s"' %
self.policies.AddLine('KEYNAME "%s\\%s"' %
(self.config['win_reg_key_name'], policy['name']))
self._PrintLine('VALUEPREFIX ""')
self.policies.AddLine('VALUEPREFIX ""')
else:
self._PrintLine('VALUENAME "%s"' % policy['name'])
self.policies.AddLine('VALUENAME "%s"' % policy['name'])
if policy['type'] in ('int-enum', 'string-enum'):
self._PrintLine('ITEMLIST', 1)
self.policies.AddLine('ITEMLIST', 1)
for item in policy['items']:
if policy['type'] == 'int-enum':
value_text = 'NUMERIC ' + str(item['value'])
else:
value_text = '"' + item['value'] + '"'
self._PrintLine('NAME !!%s_DropDown VALUE %s' %
self.policies.AddLine('NAME !!%s_DropDown VALUE %s' %
(item['name'], value_text))
self._AddGuiString(item['name'] + '_DropDown', item['caption'])
self._PrintLine('END ITEMLIST', -1)
self._PrintLine('END PART', -1)
self.policies.AddLine('END ITEMLIST', -1)
self.policies.AddLine('END PART', -1)
def WritePolicy(self, policy):
self._AddGuiString(policy['name'] + '_Policy', policy['caption'])
self._PrintLine('POLICY !!%s_Policy' % policy['name'], 1)
self.policies.AddLine('POLICY !!%s_Policy' % policy['name'], 1)
self._WriteSupported()
policy_explain_name = policy['name'] + '_Explain'
self._AddGuiString(policy_explain_name, policy['desc'])
self._PrintLine('EXPLAIN !!' + policy_explain_name)
self.policies.AddLine('EXPLAIN !!' + policy_explain_name)
if policy['type'] == 'main':
self._PrintLine('VALUENAME "%s"' % policy['name'])
self._PrintLine('VALUEON NUMERIC 1')
self._PrintLine('VALUEOFF NUMERIC 0')
self.policies.AddLine('VALUENAME "%s"' % policy['name'])
self.policies.AddLine('VALUEON NUMERIC 1')
self.policies.AddLine('VALUEOFF NUMERIC 0')
else:
self._WritePart(policy)
self._PrintLine('END POLICY', -1)
self._PrintLine()
self.policies.AddLine('END POLICY', -1)
self.policies.AddLine()
def BeginPolicyGroup(self, group):
self._open_category = len(group['policies']) > 1
......@@ -116,44 +142,78 @@ class AdmWriter(template_writer.TemplateWriter):
if self._open_category:
category_name = group['name'] + '_Category'
self._AddGuiString(category_name, group['caption'])
self._PrintLine('CATEGORY !!' + category_name, 1)
self.policies.AddLine('CATEGORY !!' + category_name, 1)
def EndPolicyGroup(self):
if self._open_category:
self._PrintLine('END CATEGORY', -1)
self.policies.AddLine('END CATEGORY', -1)
self.policies.AddLine('')
def _CreateTemplateForClass(self, policy_class, policies):
'''Creates the whole ADM template except for the [Strings] section, and
returns it as an |IndentedStringBuilder|.
Args:
policy_class: USER or MACHINE
policies: ADM code for all the policies in an |IndentedStringBuilder|.
'''
lines = IndentedStringBuilder()
category_path = self.config['win_category_path']
lines.AddLine('CLASS ' + policy_class, 1)
if self.config['build'] == 'chrome':
lines.AddLine('CATEGORY !!' + category_path[0], 1)
lines.AddLine('CATEGORY !!' + category_path[1], 1)
elif self.config['build'] == 'chromium':
lines.AddLine('CATEGORY !!' + category_path[0], 1)
lines.AddLine('KEYNAME "%s"' % self.config['win_reg_key_name'])
lines.AddLine()
lines.AddLines(policies)
if self.config['build'] == 'chrome':
lines.AddLine('END CATEGORY', -1)
lines.AddLine('END CATEGORY', -1)
lines.AddLine('', -1)
elif self.config['build'] == 'chromium':
lines.AddLine('END CATEGORY', -1)
lines.AddLine('', -1)
return lines
def BeginTemplate(self):
category_path = self.config['win_category_path']
self._AddGuiString(self.config['win_supported_os'],
self.messages['win_supported_winxpsp2']['text'])
self._PrintLine(
'CLASS ' + self.config['win_group_policy_class'].upper(),
1)
if self.config['build'] == 'chrome':
self._AddGuiString(category_path[0], 'Google')
self._AddGuiString(category_path[1], self.config['app_name'])
self._PrintLine('CATEGORY !!' + category_path[0], 1)
self._PrintLine('CATEGORY !!' + category_path[1], 1)
elif self.config['build'] == 'chromium':
self._AddGuiString(category_path[0], self.config['app_name'])
self._PrintLine('CATEGORY !!' + category_path[0], 1)
self._PrintLine('KEYNAME "%s"' % self.config['win_reg_key_name'])
self._PrintLine()
# All the policies will be written into self.policies.
# The final template text will be assembled into self.lines by
# self.EndTemplate().
def EndTemplate(self):
if self.config['build'] == 'chrome':
self._PrintLine('END CATEGORY', -1)
self._PrintLine('END CATEGORY', -1)
self._PrintLine('', -1)
elif self.config['build'] == 'chromium':
self._PrintLine('END CATEGORY', -1)
self._PrintLine('', -1)
# Copy policies into self.lines.
policy_class = self.config['win_group_policy_class'].upper()
if policy_class in ('BOTH', 'MACHINE'):
self.lines.AddLines(self._CreateTemplateForClass('MACHINE',
self.policies))
if policy_class in ('BOTH', 'USER'):
self.lines.AddLines(self._CreateTemplateForClass('USER',
self.policies))
# Copy user strings into self.lines.
self.lines.AddLine('[Strings]')
self.lines.AddLines(self.strings)
def Init(self):
self.policy_list = []
self.str_list = ['[Strings]']
self.indent = ''
# String buffer for building the whole ADM file.
self.lines = IndentedStringBuilder()
# String buffer for building the strings section of the ADM file.
self.strings = IndentedStringBuilder()
# String buffer for building the policies of the ADM file.
self.policies = IndentedStringBuilder()
def GetTemplateText(self):
lines = self.policy_list + self.str_list
return self.NEWLINE.join(lines)
return self.lines.ToString()
......@@ -24,6 +24,14 @@ from grit.tool import build
class AdmWriterUnittest(writer_unittest_common.WriterUnittestCommon):
'''Unit tests for AdmWriter.'''
def ConstructOutput(self, classes, body, strings):
result = []
for clazz in classes:
result.append('CLASS ' + clazz)
result.append(body)
result.append(strings)
return ''.join(result)
def CompareOutputs(self, output, expected_output):
'''Compares the output of the adm_writer with its expected output.
......@@ -51,15 +59,16 @@ class AdmWriterUnittest(writer_unittest_common.WriterUnittestCommon):
}
}''')
output = self.GetOutput(grd, 'fr', {'_chromium': '1',}, 'adm', 'en')
expected_output = '''CLASS MACHINE
expected_output = self.ConstructOutput(
['MACHINE', 'USER'], '''
CATEGORY !!chromium
KEYNAME "Software\\Policies\\Chromium"
END CATEGORY
[Strings]
''', '''[Strings]
SUPPORTED_WINXPSP2="At least "Windows 3.11"
chromium="Chromium"'''
chromium="Chromium"''')
self.CompareOutputs(output, expected_output)
def testMainPolicy(self):
......@@ -83,7 +92,8 @@ chromium="Chromium"'''
}
}''')
output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'adm', 'en')
expected_output = '''CLASS MACHINE
expected_output = self.ConstructOutput(
['MACHINE', 'USER'], '''
CATEGORY !!google
CATEGORY !!googlechrome
KEYNAME "Software\\Policies\\Google\\Chrome"
......@@ -101,12 +111,12 @@ chromium="Chromium"'''
END CATEGORY
END CATEGORY
[Strings]
''', '''[Strings]
SUPPORTED_WINXPSP2="At least Windows 3.12"
google="Google"
googlechrome="Google Chrome"
MainPolicy_Policy="Caption of main."
MainPolicy_Explain="Description of main."'''
MainPolicy_Explain="Description of main."''')
self.CompareOutputs(output, expected_output)
def testStringPolicy(self):
......@@ -131,7 +141,8 @@ With a newline.""",
}
}''')
output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
expected_output = '''CLASS MACHINE
expected_output = self.ConstructOutput(
['MACHINE', 'USER'], '''
CATEGORY !!chromium
KEYNAME "Software\\Policies\\Chromium"
......@@ -148,13 +159,13 @@ With a newline.""",
END CATEGORY
[Strings]
''', '''[Strings]
SUPPORTED_WINXPSP2="At least Windows 3.13"
chromium="Chromium"
StringPolicy_Policy="Caption of policy."
StringPolicy_Explain="Description of group.\\nWith a newline."
StringPolicy_Part="Caption of policy."
'''
''')
self.CompareOutputs(output, expected_output)
def testIntPolicy(self):
......@@ -178,7 +189,8 @@ StringPolicy_Part="Caption of policy."
}
}''')
output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
expected_output = '''CLASS MACHINE
expected_output = self.ConstructOutput(
['MACHINE', 'USER'], '''
CATEGORY !!chromium
KEYNAME "Software\\Policies\\Chromium"
......@@ -195,13 +207,13 @@ StringPolicy_Part="Caption of policy."
END CATEGORY
[Strings]
''', '''[Strings]
SUPPORTED_WINXPSP2="At least Windows 3.13"
chromium="Chromium"
IntPolicy_Policy="Caption of policy."
IntPolicy_Explain="Description of policy."
IntPolicy_Part="Caption of policy."
'''
''')
self.CompareOutputs(output, expected_output)
def testIntEnumPolicy(self):
......@@ -237,7 +249,8 @@ IntPolicy_Part="Caption of policy."
}
}''')
output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'adm', 'en')
expected_output = '''CLASS MACHINE
expected_output = self.ConstructOutput(
['MACHINE', 'USER'], '''
CATEGORY !!google
CATEGORY !!googlechrome
KEYNAME "Software\\Policies\\Google\\Chrome"
......@@ -260,7 +273,7 @@ IntPolicy_Part="Caption of policy."
END CATEGORY
END CATEGORY
[Strings]
''', '''[Strings]
SUPPORTED_WINXPSP2="At least Windows 3.14"
google="Google"
googlechrome="Google Chrome"
......@@ -269,7 +282,7 @@ EnumPolicy_Explain="Description of policy."
EnumPolicy_Part="Caption of policy."
ProxyServerDisabled_DropDown="Option1"
ProxyServerAutoDetect_DropDown="Option2"
'''
''')
self.CompareOutputs(output, expected_output)
def testStringEnumPolicy(self):
......@@ -299,7 +312,8 @@ ProxyServerAutoDetect_DropDown="Option2"
}
}''')
output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'adm', 'en')
expected_output = '''CLASS MACHINE
expected_output = self.ConstructOutput(
['MACHINE', 'USER'], '''
CATEGORY !!google
CATEGORY !!googlechrome
KEYNAME "Software\\Policies\\Google\\Chrome"
......@@ -322,7 +336,7 @@ ProxyServerAutoDetect_DropDown="Option2"
END CATEGORY
END CATEGORY
[Strings]
''', '''[Strings]
SUPPORTED_WINXPSP2="At least Windows 3.14"
google="Google"
googlechrome="Google Chrome"
......@@ -331,7 +345,7 @@ EnumPolicy_Explain="Description of policy."
EnumPolicy_Part="Caption of policy."
ProxyServerDisabled_DropDown="Option1"
ProxyServerAutoDetect_DropDown="Option2"
'''
''')
self.CompareOutputs(output, expected_output)
def testListPolicy(self):
......@@ -357,7 +371,8 @@ With a newline.""",
},
}''')
output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
expected_output = '''CLASS MACHINE
expected_output = self.ConstructOutput(
['MACHINE', 'USER'], '''
CATEGORY !!chromium
KEYNAME "Software\\Policies\\Chromium"
......@@ -375,13 +390,13 @@ With a newline.""",
END CATEGORY
[Strings]
''', '''[Strings]
SUPPORTED_WINXPSP2="At least Windows 3.15"
chromium="Chromium"
ListPolicy_Policy="Caption of list policy."
ListPolicy_Explain="Description of list policy.\\nWith a newline."
ListPolicy_Part="Label of list policy."
'''
''')
self.CompareOutputs(output, expected_output)
def testNonSupportedPolicy(self):
......@@ -412,16 +427,17 @@ ListPolicy_Part="Label of list policy."
}
}''')
output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
expected_output = '''CLASS MACHINE
expected_output = self.ConstructOutput(
['MACHINE', 'USER'], '''
CATEGORY !!chromium
KEYNAME "Software\\Policies\\Chromium"
END CATEGORY
[Strings]
''', '''[Strings]
SUPPORTED_WINXPSP2="At least Windows 3.16"
chromium="Chromium"
'''
''')
self.CompareOutputs(output, expected_output)
def testPolicyGroup(self):
......@@ -459,7 +475,8 @@ With a newline."""
}
}''')
output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
expected_output = '''CLASS MACHINE
expected_output = self.ConstructOutput(
['MACHINE', 'USER'], '''
CATEGORY !!chromium
KEYNAME "Software\\Policies\\Chromium"
......@@ -488,9 +505,10 @@ With a newline."""
END POLICY
END CATEGORY
END CATEGORY
[Strings]
''', '''[Strings]
SUPPORTED_WINXPSP2="At least Windows 3.16"
chromium="Chromium"
Group1_Category="Caption of group."
......@@ -500,7 +518,7 @@ Policy1_Part="Caption of policy1."
Policy2_Policy="Caption of policy2."
Policy2_Explain="Description of policy2.\\nWith a newline."
Policy2_Part="Caption of policy2."
'''
''')
self.CompareOutputs(output, expected_output)
if __name__ == '__main__':
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment