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

Add Mac output for policy template generator

Writer for plist manifest and string table files, and custom strings for the Mac templates.

BUG=49316
TEST=plist_writer_unittest.*, plist_strings_writer_unittest.* (grit)

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57307 0039d316-1c4b-4281-b951-d872f2087c98
parent 084ac015
This diff is collapsed.
[ {
# policy_templates.json - Metafile for policy templates # policy_templates.json - Metafile for policy templates
# #
# This file is used as input to generate the following policy templates: # This file is used as input to generate the following policy templates:
...@@ -79,125 +79,133 @@ ...@@ -79,125 +79,133 @@
# e.g. the name of the caption of ProxyServerDisabled: # e.g. the name of the caption of ProxyServerDisabled:
# IDS_POLICY_ENUM_PROXYSERVERDISABLED_CAPTION # IDS_POLICY_ENUM_PROXYSERVERDISABLED_CAPTION
# #
# The homepage-related policies are split into two groups, because if they 'policy_groups': [
# are in the same group, then Windows does not allow to set them undefined # The homepage-related policies are split into two groups, because if they
# independently of each other. # are in the same group, then Windows does not allow to set them undefined
{ # independently of each other.
'name': 'HomepageLocation', {
'policies': [{ 'name': 'HomepageLocation',
'name': 'HomepageLocation', 'policies': [{
'type': 'string', 'name': 'HomepageLocation',
}], 'type': 'string',
}, }],
{ },
'name': 'HomepageIsNewTabPage', {
'policies': [{
'name': 'HomepageIsNewTabPage', 'name': 'HomepageIsNewTabPage',
'type': 'main', 'policies': [{
}], 'name': 'HomepageIsNewTabPage',
}, 'type': 'main',
{ }],
'name': 'ApplicationLocale', },
'policies': [{ {
'name': 'ApplicationLocaleValue', 'name': 'ApplicationLocale',
'type': 'string', 'policies': [{
}] 'name': 'ApplicationLocaleValue',
}, 'type': 'string',
{ }]
'name': 'AlternateErrorPagesEnabled', },
'policies': [{ {
'name': 'AlternateErrorPagesEnabled', 'name': 'AlternateErrorPagesEnabled',
'type': 'main', 'policies': [{
}] 'name': 'AlternateErrorPagesEnabled',
}, 'type': 'main',
{ }]
'name': 'SearchSuggestEnabled', },
'policies': [{ {
'name': 'SearchSuggestEnabled', 'name': 'SearchSuggestEnabled',
'type': 'main' 'policies': [{
}], 'name': 'SearchSuggestEnabled',
}, 'type': 'main'
{ }],
'name': 'DnsPrefetchingEnabled', },
'policies': [{ {
'name': 'DnsPrefetchingEnabled', 'name': 'DnsPrefetchingEnabled',
'type': 'main' 'policies': [{
}], 'name': 'DnsPrefetchingEnabled',
}, 'type': 'main'
{ }],
'name': 'SafeBrowsingEnabled', },
'policies': [{ {
'name': 'SafeBrowsingEnabled', 'name': 'SafeBrowsingEnabled',
'type': 'main', 'policies': [{
}] 'name': 'SafeBrowsingEnabled',
}, 'type': 'main',
{ }]
'name': 'MetricsReportingEnabled', },
'policies': [{ {
'name': 'MetricsReportingEnabled', 'name': 'MetricsReportingEnabled',
'type': 'main' 'policies': [{
}], 'name': 'MetricsReportingEnabled',
}, 'type': 'main'
{ }],
'name': 'PasswordManagerEnabled', },
'policies': [{ {
'name': 'PasswordManagerEnabled', 'name': 'PasswordManagerEnabled',
'type': 'main', 'policies': [{
}] 'name': 'PasswordManagerEnabled',
}, 'type': 'main',
{ }]
'name': 'DisabledPlugins', },
'policies': [{ {
'name': 'DisabledPluginsList', 'name': 'DisabledPlugins',
'type': 'string', 'policies': [{
}] 'name': 'DisabledPluginsList',
}, 'type': 'string',
{ }]
'name': 'SyncDisabled', },
'policies': [{ {
'name': 'SyncDisabled', 'name': 'SyncDisabled',
'type': 'main', 'policies': [{
}] 'name': 'SyncDisabled',
}, 'type': 'main',
{ }]
'name': 'Proxy', },
'policies': [ {
{ 'name': 'Proxy',
'name': 'ProxyServerMode', 'policies': [
'type': 'enum', {
'items': [ 'name': 'ProxyServerMode',
{'name': 'ProxyServerDisabled', 'value': '0'}, 'type': 'enum',
{'name': 'ProxyServerAutoDetect', 'value': '1'}, 'items': [
{'name': 'ProxyServerManual', 'value': '2'}, {'name': 'ProxyServerDisabled', 'value': '0'},
{'name': 'ProxyServerUseSystem', 'value': '3'}, {'name': 'ProxyServerAutoDetect', 'value': '1'},
], {'name': 'ProxyServerManual', 'value': '2'},
}, {'name': 'ProxyServerUseSystem', 'value': '3'},
{ ],
'name': 'ProxyServer', },
'type': 'string' {
}, 'name': 'ProxyServer',
{ 'type': 'string'
'name': 'ProxyPacUrl', },
'type': 'string' {
}, 'name': 'ProxyPacUrl',
{ 'type': 'string'
'name': 'ProxyBypassList', },
'type': 'string' {
}, 'name': 'ProxyBypassList',
] 'type': 'string'
}, },
{ ]
'name': 'ExtensionInstallBlacklist', },
'policies': [{ {
'name': 'ExtensionInstallBlacklist', 'name': 'ExtensionInstallBlacklist',
'type': 'list', 'policies': [{
}] 'name': 'ExtensionInstallBlacklist',
}, 'type': 'list',
{ }]
'name': 'ExtensionInstallWhitelist', },
'policies': [{ {
'name': 'ExtensionInstallWhitelist', 'name': 'ExtensionInstallWhitelist',
'type': 'list', 'policies': [{
}] 'name': 'ExtensionInstallWhitelist',
} 'type': 'list',
] }]
\ No newline at end of file }
],
'placeholders': [
{
'key': '$2',
'value': 'http://www.chromium.org/developers/design-documents/network-settings#TOC-Command-line-options-for-proxy-sett'
},
]
}
\ No newline at end of file
...@@ -1796,6 +1796,10 @@ ...@@ -1796,6 +1796,10 @@
}], }],
], ],
}, },
]}, # 'targets'
], # OS=="win"
['OS=="win" or OS=="mac"',
{ 'targets': [
{ {
# policy_templates has different inputs and outputs, so it can't use # policy_templates has different inputs and outputs, so it can't use
# the rules of chrome_strings # the rules of chrome_strings
...@@ -1836,6 +1840,9 @@ ...@@ -1836,6 +1840,9 @@
['use_titlecase_in_grd_files==1', { ['use_titlecase_in_grd_files==1', {
'action': ['-D', 'use_titlecase'], 'action': ['-D', 'use_titlecase'],
}], }],
['OS == "mac"', {
'action': ['-D', 'mac_bundle_id=<(mac_bundle_id)'],
}],
], ],
'message': 'Generating policy templates from <(input_path)', 'message': 'Generating policy templates from <(input_path)',
}, },
...@@ -1852,7 +1859,7 @@ ...@@ -1852,7 +1859,7 @@
], ],
}, },
]}, # 'targets' ]}, # 'targets'
], # OS=="win" ], # OS=="win" or OS=="mac"
['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', { ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
'targets': [{ 'targets': [{
'target_name': 'packed_resources', 'target_name': 'packed_resources',
......
...@@ -59,7 +59,7 @@ class TemplateFormatter(interface.ItemFormatter): ...@@ -59,7 +59,7 @@ class TemplateFormatter(interface.ItemFormatter):
self._lang = lang self._lang = lang
self._GetFlags(item) self._GetFlags(item)
self._policy_groups = None self._policy_data = None
self._messages = {} self._messages = {}
self._ParseGritNodes(item) self._ParseGritNodes(item)
return self._GetOutput() return self._GetOutput()
...@@ -72,8 +72,9 @@ class TemplateFormatter(interface.ItemFormatter): ...@@ -72,8 +72,9 @@ class TemplateFormatter(interface.ItemFormatter):
The text of the policy template based on the parameters passed The text of the policy template based on the parameters passed
to __init__() and Format(). to __init__() and Format().
''' '''
policy_generator = \ policy_generator = PolicyTemplateGenerator(
PolicyTemplateGenerator(self._messages, self._policy_groups) self._messages,
self._policy_data['policy_groups'])
writer = self._writer_module.GetWriter(self._info, self._messages) writer = self._writer_module.GetWriter(self._info, self._messages)
str = policy_generator.GetTemplateText(writer) str = policy_generator.GetTemplateText(writer)
return str return str
...@@ -107,8 +108,14 @@ class TemplateFormatter(interface.ItemFormatter): ...@@ -107,8 +108,14 @@ class TemplateFormatter(interface.ItemFormatter):
message: A <message> node in the grit tree. message: A <message> node in the grit tree.
''' '''
msg_name = message.GetTextualIds()[0] msg_name = message.GetTextualIds()[0]
# Get translation of message.
msg_txt = message.Translate(self._lang) msg_txt = message.Translate(self._lang)
# Replace the placeholder of app name.
msg_txt = msg_txt.replace('$1', self._info['app_name']) msg_txt = msg_txt.replace('$1', self._info['app_name'])
# Replace other placeholders.
for placeholder in self._policy_data['placeholders']:
msg_txt = msg_txt.replace(placeholder['key'], placeholder['value'])
# Strip spaces and escape newlines.
lines = msg_txt.split('\n') lines = msg_txt.split('\n')
lines = [line.strip() for line in lines] lines = [line.strip() for line in lines]
msg_txt = "\\n".join(lines) msg_txt = "\\n".join(lines)
...@@ -126,8 +133,8 @@ class TemplateFormatter(interface.ItemFormatter): ...@@ -126,8 +133,8 @@ class TemplateFormatter(interface.ItemFormatter):
return return
if (isinstance(item, structure.StructureNode) and if (isinstance(item, structure.StructureNode) and
item.attrs['type'] == 'policy_template_metafile'): item.attrs['type'] == 'policy_template_metafile'):
assert self._policy_groups == None assert self._policy_data == None
self._policy_groups = item.gatherer.GetData() self._policy_data = item.gatherer.GetData()
elif (isinstance(item, message.MessageNode)): elif (isinstance(item, message.MessageNode)):
self._ImportMessage(item) self._ImportMessage(item)
for child in item.children: for child in item.children:
......
...@@ -3,14 +3,18 @@ ...@@ -3,14 +3,18 @@
# found in the LICENSE file. # found in the LICENSE file.
from template_writer import TemplateWriter from grit.format.policy_templates.writers import template_writer
def GetWriter(info, messages): def GetWriter(info, messages):
'''Factory method for creating AdmWriter objects.
See the constructor of TemplateWriter for description of
arguments.
'''
return AdmWriter(info, messages) return AdmWriter(info, messages)
class AdmWriter(TemplateWriter): class AdmWriter(template_writer.TemplateWriter):
'''Class for generating policy templates in Windows ADM format. '''Class for generating policy templates in Windows ADM format.
It is used by PolicyTemplateGenerator to write ADM files. It is used by PolicyTemplateGenerator to write ADM files.
''' '''
......
# 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.policy_templates.writers import template_writer
def GetWriter(info, messages):
'''Factory method for creating PListStringsWriter objects.
See the constructor of TemplateWriter for description of
arguments.
'''
return PListStringsWriter(info, messages)
class PListStringsWriter(template_writer.TemplateWriter):
'''Outputs localized string table files for the Mac policy file.
These files are named Localizable.strings and they are in the
[lang].lproj subdirectories of the manifest bundle.
'''
def _GetLocalizedPolicyMessage(self, policy, msg_id):
'''Looks up localized caption or description for a policy.
If the policy does not have the required message, then it is
inherited from the group.
Args:
policy: The data structure of the policy.
msg_id: Either 'caption' or 'desc'.
Returns:
The corresponding message for the policy.
'''
if msg_id in policy:
msg = policy[msg_id]
else:
msg = self._policy_group[msg_id]
return msg
def _AddToStringTable(self, item_name, title, desc):
'''Add a title and a description of an item to the string table.
Args:
item_name: The name of the item that will get the title and the
description.
title: The text of the title to add.
desc: The text of the description to add.
'''
title = title.replace('"', '\\"')
desc = desc.replace('"', '\\"')
self._out.append('%s.pfm_title = \"%s\";' % (item_name, title))
self._out.append('%s.pfm_description = \"%s\";' % (item_name, desc))
def WritePolicy(self, policy):
'''Add strings to the stringtable corresponding a given policy.
Args:
policy: The policy for which the strings will be added to the
string table.
'''
desc = self._GetLocalizedPolicyMessage(policy, 'desc')
caption = self._GetLocalizedPolicyMessage(policy, 'caption')
if (policy['type'] == 'enum'):
# Append the captions of enum items to the description string.
item_descs = []
for item in policy['items']:
item_descs.append( item['value'] + ' - ' + item['caption'] )
desc = '\\n'.join(item_descs) + '\\n' + desc
self._AddToStringTable(policy['name'], caption, desc)
def BeginPolicyGroup(self, group):
self._policy_group = group
def EndPolicyGroup(self):
self._policy_group = None
def BeginTemplate(self):
self._AddToStringTable(
self.info['app_name'],
self.info['app_name'],
self.messages['IDS_POLICY_MAC_CHROME_PREFERENCES'])
def EndTemplate(self):
pass
def Prepare(self):
# A buffer for the lines of the string table being generated.
self._out = []
def GetTemplateText(self):
return '\n'.join(self._out)
#!/usr/bin/python2.4
# 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.
'''Unit tests for grit.format.policy_templates.writers.plist_strings_writer'''
import os
import sys
if __name__ == '__main__':
sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..'))
import tempfile
import unittest
import StringIO
from grit.format.policy_templates.writers import writer_unittest_common
from grit import grd_reader
from grit import util
from grit.tool import build
class PListStringsWriterUnittest(writer_unittest_common.WriterUnittestCommon):
'''Unit tests for PListWriter.'''
def testEmpty(self):
# Test PListWriter in case of empty polices.
grd = self.prepareTest('''
{
'policy_groups': [],
'placeholders': [],
}''', '''
<grit base_dir="." latest_public_release="0" current_release="1" source_lang_id="en">
<release seq="1">
<structures>
<structure name="IDD_POLICY_SOURCE_FILE" file="%s" type="policy_template_metafile" />
</structures>
<messages>
<message name="IDS_POLICY_MAC_CHROME_PREFERENCES">$1 preferen"ces</message>
</messages>
</release>
</grit>
''' )
self.CompareResult(
grd,
'fr',
{'_chromium': '1', 'mac_bundle_id': 'com.example.Test'},
'plist_strings',
'en',
'''Chromium.pfm_title = "Chromium";
Chromium.pfm_description = "Chromium preferen\\"ces";
''')
def testMainPolicy(self):
# Tests a policy group with a single policy of type 'main'.
grd = self.prepareTest('''
{
'policy_groups': [
{
'name': 'MainGroup',
'policies': [{
'name': 'MainPolicy',
'type': 'main',
}],
},
],
'placeholders': [],
}''', '''
<grit base_dir="." latest_public_release="0" current_release="1" source_lang_id="en">
<release seq="1">
<structures>
<structure name="IDD_POLICY_SOURCE_FILE" file="%s" type="policy_template_metafile" />
</structures>
<messages>
<message name="IDS_POLICY_GROUP_MAINGROUP_CAPTION">Caption of main.</message>
<message name="IDS_POLICY_GROUP_MAINGROUP_DESC">Title of main.</message>
<message name="IDS_POLICY_MAC_CHROME_PREFERENCES">Preferences of $1</message>
</messages>
</release>
</grit>
''' )
self.CompareResult(
grd,
'fr',
{'_google_chrome' : '1', 'mac_bundle_id': 'com.example.Test'},
'plist_strings',
'en',
'''Google Chrome.pfm_title = "Google Chrome";
Google Chrome.pfm_description = "Preferences of Google Chrome";
MainPolicy.pfm_title = "Caption of main.";
MainPolicy.pfm_description = "Title of main.";
''')
def testStringPolicy(self):
# Tests a policy group with a single policy of type 'string'. Also test
# inheriting group description to policy description.
grd = self.prepareTest('''
{
'policy_groups': [
{
'name': 'StringGroup',
'policies': [{
'name': 'StringPolicy',
'type': 'string',
}],
},
],
'placeholders': [],
}''', '''
<grit base_dir="." latest_public_release="0" current_release="1" source_lang_id="en">
<release seq="1">
<structures>
<structure name="IDD_POLICY_SOURCE_FILE" file="%s" type="policy_template_metafile" />
</structures>
<messages>
<message name="IDS_POLICY_GROUP_STRINGGROUP_CAPTION">Caption of group.</message>
<message name="IDS_POLICY_GROUP_STRINGGROUP_DESC">Description of group.
With a newline.</message>
<message name="IDS_POLICY_STRINGPOLICY_CAPTION">Caption of policy.</message>
<message name="IDS_POLICY_MAC_CHROME_PREFERENCES">Preferences Of $1</message>
</messages>
</release>
</grit>
''' )
self.CompareResult(
grd,
'fr',
{'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
'plist_strings',
'en',
'''Chromium.pfm_title = "Chromium";
Chromium.pfm_description = "Preferences Of Chromium";
StringPolicy.pfm_title = "Caption of policy.";
StringPolicy.pfm_description = "Description of group.\\nWith a newline.";
''')
def testEnumPolicy(self):
# Tests a policy group with a single policy of type 'enum'.
grd = self.prepareTest('''
{
'policy_groups': [
{
'name': 'EnumGroup',
'policies': [{
'name': 'EnumPolicy',
'type': 'enum',
'items': [
{'name': 'ProxyServerDisabled', 'value': '0'},
{'name': 'ProxyServerAutoDetect', 'value': '1'},
]
}],
},
],
'placeholders': [],
}''', '''
<grit base_dir="." latest_public_release="0" current_release="1" source_lang_id="en">
<release seq="1">
<structures>
<structure name="IDD_POLICY_SOURCE_FILE" file="%s" type="policy_template_metafile" />
</structures>
<messages>
<message name="IDS_POLICY_GROUP_ENUMGROUP_CAPTION">Caption of group.</message>
<message name="IDS_POLICY_GROUP_ENUMGROUP_DESC">Description of group.</message>
<message name="IDS_POLICY_ENUMPOLICY_CAPTION">Caption of policy.</message>
<message name="IDS_POLICY_ENUMPOLICY_DESC">Description of policy.</message>
<message name="IDS_POLICY_ENUM_PROXYSERVERDISABLED_CAPTION">Option1</message>
<message name="IDS_POLICY_ENUM_PROXYSERVERAUTODETECT_CAPTION">Option2</message>
<message name="IDS_POLICY_MAC_CHROME_PREFERENCES">$1 preferences</message>
</messages>
</release>
</grit>
''' )
self.CompareResult(
grd,
'fr',
{'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
'plist_strings',
'en',
'''Google Chrome.pfm_title = "Google Chrome";
Google Chrome.pfm_description = "Google Chrome preferences";
EnumPolicy.pfm_title = "Caption of policy.";
EnumPolicy.pfm_description = "0 - Option1\\n1 - Option2\\nDescription of policy.";
''')
if __name__ == '__main__':
unittest.main()
# 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 xml.dom import minidom
from grit.format.policy_templates.writers import xml_formatted_writer
def GetWriter(info, messages):
'''Factory method for creating PListWriter objects.
See the constructor of TemplateWriter for description of
arguments.
'''
return PListWriter(info, messages)
class PListWriter(xml_formatted_writer.XMLFormattedWriter):
'''Class for generating policy templates in Mac plist format.
It is used by PolicyTemplateGenerator to write plist files.
'''
STRING_TABLE = 'Localizable.strings'
TYPE_TO_INPUT = {
'string': 'string',
'enum': 'integer',
'main': 'boolean',
'list': 'array',
}
def _AddKeyValuePair(self, parent, key_string, value_tag):
'''Adds a plist key-value pair to a parent XML element.
A key-value pair in plist consists of two XML elements next two each other:
<key>key_string</key>
<value_tag>...</value_tag>
Args:
key_string: The content of the key tag.
value_tag: The name of the value element.
Returns:
The XML element of the value tag.
'''
self.AddElement(parent, 'key', {}, key_string)
return self.AddElement(parent, value_tag)
def _AddStringKeyValuePair(self, parent, key_string, value_string):
'''Adds a plist key-value pair to a parent XML element, where the
value element contains a string. The name of the value element will be
<string>.
Args:
key_string: The content of the key tag.
value_string: The content of the value tag.
'''
self.AddElement(parent, 'key', {}, key_string)
self.AddElement(parent, 'string', {}, value_string)
def _AddTargets(self, parent):
'''Adds the following XML snippet to an XML element:
<key>pfm_targets</key>
<array>
<string>user-managed</string>
</array>
Args:
parent: The parent XML element where the snippet will be added.
'''
array = self._AddKeyValuePair(parent, 'pfm_targets', 'array')
self.AddElement(array, 'string', {}, 'user-managed')
def WritePolicy(self, policy):
policy_name = policy['name']
policy_type = policy['type']
dict = self.AddElement(self._array, 'dict')
self._AddStringKeyValuePair(dict, 'pfm_name', policy_name)
# Set empty strings for title and description. They will be taken by the
# OSX Workgroup Manager from the string table in a Localizable.strings file.
# Those files are generated by plist_strings_writer.
self._AddStringKeyValuePair(dict, 'pfm_description', '')
self._AddStringKeyValuePair(dict, 'pfm_title', '')
self._AddTargets(dict)
self._AddStringKeyValuePair(dict, 'pfm_type',
self.TYPE_TO_INPUT[policy_type])
if (policy_type == 'enum'):
range_list = self._AddKeyValuePair(dict, 'pfm_range_list', 'array')
for item in policy['items']:
self.AddElement(range_list, 'integer', {}, item['value'])
def BeginPolicyGroup(self, group):
pass
def EndPolicyGroup(self):
pass
def BeginTemplate(self):
self._plist.attributes['version'] = '1'
dict = self.AddElement(self._plist, 'dict')
self._AddStringKeyValuePair(dict, 'pfm_name', self.info['app_name'])
self._AddStringKeyValuePair(dict, 'pfm_description', '')
self._AddStringKeyValuePair(dict, 'pfm_title', '')
self._AddStringKeyValuePair(dict, 'pfm_version', '1')
self._AddStringKeyValuePair(dict, 'pfm_domain', self.info['mac_bundle_id'])
self._array = self._AddKeyValuePair(dict, 'pfm_subkeys', 'array')
def EndTemplate(self):
pass
def Prepare(self):
dom_impl = minidom.getDOMImplementation('')
doctype = dom_impl.createDocumentType(
'plist',
'-//Apple//DTD PLIST 1.0//EN',
'http://www.apple.com/DTDs/PropertyList-1.0.dtd')
self._doc = dom_impl.createDocument(None, 'plist', doctype)
self._plist = self._doc.documentElement
def GetTemplateText(self):
# return self.plist_doc.toprettyxml(indent=' ')
# The above pretty-printer does not print the doctype and adds spaces
# around texts, which the OSX Workgroup Manager does not like. So we use
# the poor man's pretty printer. It assumes that there are no mixed-content
# nodes.
# Get all the XML content in a one-line string.
xml = self._doc.toxml()
# Determine where the line breaks will be. (They will only be between tags.)
lines = xml[1:len(xml)-1].split('><')
indent = ''
res = ''
# Determine indent for each line.
for i in range(len(lines)):
line = lines[i]
if line[0] == '/':
# If the current line starts with a closing tag, decrease indent before
# printing.
indent = indent[2:]
lines[i] = indent + '<' + line + '>'
if (line[0] not in ['/', '?', '!'] and '</' not in line and
line[len(line)-1] != '/'):
# If the current line starts with an opening tag and does not conatin a
# closing tag, increase indent after the line is printed.
indent += ' '
# Reconstruct XML text from the lines.
return '\n'.join(lines)
# 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.
'''Unit tests for grit.format.policy_templates.writers.plist_writer'''
import os
import re
import sys
if __name__ == '__main__':
sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..'))
import tempfile
import unittest
import StringIO
from xml.dom import minidom
from grit.format import rc
from grit.format.policy_templates.writers import writer_unittest_common
from grit import grd_reader
from grit import util
from grit.tool import build
class PListWriterUnittest(writer_unittest_common.WriterUnittestCommon):
'''Unit tests for PListWriter.'''
def _GetExpectedResults(self, product_name, bundle_id, policies):
'''Substitutes the variable parts into a plist template. The result
of this function can be used as an expected result to test the output
of PListWriter.
Args:
product_name: The name of the product, normally Chromium or Google Chrome.
bundle_id: The mac bundle id of the product.
policies: The list of policies.
Returns:
The text of a plist template with the variable parts substituted.
'''
return '''
<?xml version="1.0" ?>
<!DOCTYPE plist PUBLIC '-//Apple//DTD PLIST 1.0//EN' 'http://www.apple.com/DTDs/PropertyList-1.0.dtd'>
<plist version="1">
<dict>
<key>pfm_name</key>
<string>%s</string>
<key>pfm_description</key>
<string/>
<key>pfm_title</key>
<string/>
<key>pfm_version</key>
<string>1</string>
<key>pfm_domain</key>
<string>%s</string>
<key>pfm_subkeys</key>
%s
</dict>
</plist>''' % (product_name, bundle_id, policies)
def testEmpty(self):
# Test PListWriter in case of empty polices.
grd = self.prepareTest('''
{
'policy_groups': [],
'placeholders': [],
}''', '''
<grit base_dir="." latest_public_release="0" current_release="1" source_lang_id="en">
<release seq="1">
<structures>
<structure name="IDD_POLICY_SOURCE_FILE" file="%s" type="policy_template_metafile" />
</structures>
<messages />
</release>
</grit>
''' )
self.CompareResult(
grd,
'fr',
{'_chromium': '1', 'mac_bundle_id': 'com.example.Test'},
'plist',
'en',
self._GetExpectedResults('Chromium', 'com.example.Test', '<array/>'))
def testMainPolicy(self):
# Tests a policy group with a single policy of type 'main'.
grd = self.prepareTest('''
{
'policy_groups': [
{
'name': 'MainGroup',
'policies': [{
'name': 'MainPolicy',
'type': 'main',
}],
},
],
'placeholders': [],
}''', '''
<grit base_dir="." latest_public_release="0" current_release="1" source_lang_id="en">
<release seq="1">
<structures>
<structure name="IDD_POLICY_SOURCE_FILE" file="%s" type="policy_template_metafile" />
</structures>
<messages>
<message name="IDS_POLICY_GROUP_MAINGROUP_CAPTION">This is not tested here.</message>
<message name="IDS_POLICY_GROUP_MAINGROUP_DESC">This is not tested here.</message>
</messages>
</release>
</grit>
''' )
self.CompareResult(
grd,
'fr',
{'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
'plist',
'en',
self._GetExpectedResults('Chromium', 'com.example.Test', '''<array>
<dict>
<key>pfm_name</key>
<string>MainPolicy</string>
<key>pfm_description</key>
<string/>
<key>pfm_title</key>
<string/>
<key>pfm_targets</key>
<array>
<string>user-managed</string>
</array>
<key>pfm_type</key>
<string>boolean</string>
</dict>
</array>'''))
def testStringPolicy(self):
# Tests a policy group with a single policy of type 'string'.
grd = self.prepareTest('''
{
'policy_groups': [
{
'name': 'StringGroup',
'policies': [{
'name': 'StringPolicy',
'type': 'string',
}],
},
],
'placeholders': [],
}''', '''
<grit base_dir="." latest_public_release="0" current_release="1" source_lang_id="en">
<release seq="1">
<structures>
<structure name="IDD_POLICY_SOURCE_FILE" file="%s" type="policy_template_metafile" />
</structures>
<messages>
<message name="IDS_POLICY_GROUP_STRINGGROUP_CAPTION">This is not tested here.</message>
<message name="IDS_POLICY_GROUP_STRINGGROUP_DESC">This is not tested here.</message>
<message name="IDS_POLICY_STRINGPOLICY_CAPTION">This is not tested here.</message>
<message name="IDS_POLICY_STRINGPOLICY_DESC">This is not tested here.</message>
</messages>
</release>
</grit>
''' )
self.CompareResult(
grd,
'fr',
{'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
'plist',
'en',
self._GetExpectedResults('Chromium', 'com.example.Test', '''<array>
<dict>
<key>pfm_name</key>
<string>StringPolicy</string>
<key>pfm_description</key>
<string/>
<key>pfm_title</key>
<string/>
<key>pfm_targets</key>
<array>
<string>user-managed</string>
</array>
<key>pfm_type</key>
<string>string</string>
</dict>
</array>'''))
def testEnumPolicy(self):
# Tests a policy group with a single policy of type 'enum'.
grd = self.prepareTest('''
{
'policy_groups': [
{
'name': 'EnumGroup',
'policies': [{
'name': 'EnumPolicy',
'type': 'enum',
'items': [
{'name': 'ProxyServerDisabled', 'value': '0'},
{'name': 'ProxyServerAutoDetect', 'value': '1'},
]
}],
},
],
'placeholders': [],
}''', '''
<grit base_dir="." latest_public_release="0" current_release="1" source_lang_id="en">
<release seq="1">
<structures>
<structure name="IDD_POLICY_SOURCE_FILE" file="%s" type="policy_template_metafile" />
</structures>
<messages>
<message name="IDS_POLICY_GROUP_ENUMGROUP_CAPTION">This is not tested here.</message>
<message name="IDS_POLICY_GROUP_ENUMGROUP_DESC">This is not tested here.</message>
<message name="IDS_POLICY_ENUMPOLICY_CAPTION">This is not tested here.</message>
<message name="IDS_POLICY_ENUMPOLICY_DESC">This is not tested here.</message>
<message name="IDS_POLICY_ENUM_PROXYSERVERDISABLED_CAPTION">This is not tested here.</message>
<message name="IDS_POLICY_ENUM_PROXYSERVERAUTODETECT_CAPTION">This is not tested here.</message>
</messages>
</release>
</grit>
''' )
self.CompareResult(
grd,
'fr',
{'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
'plist',
'en',
self._GetExpectedResults('Google Chrome', 'com.example.Test2', '''<array>
<dict>
<key>pfm_name</key>
<string>EnumPolicy</string>
<key>pfm_description</key>
<string/>
<key>pfm_title</key>
<string/>
<key>pfm_targets</key>
<array>
<string>user-managed</string>
</array>
<key>pfm_type</key>
<string>integer</string>
<key>pfm_range_list</key>
<array>
<integer>0</integer>
<integer>1</integer>
</array>
</dict>
</array>'''))
if __name__ == '__main__':
unittest.main()
# 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.
'''Common tools for unit-testing writers.'''
import os
import sys
if __name__ == '__main__':
sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..'))
import tempfile
import unittest
import StringIO
from grit import grd_reader
from grit import util
from grit.tool import build
class DummyOutput(object):
def __init__(self, type, language, file = 'hello.gif'):
self.type = type
self.language = language
self.file = file
def GetType(self):
return self.type
def GetLanguage(self):
return self.language
def GetOutputFilename(self):
return self.file
class WriterUnittestCommon(unittest.TestCase):
'''Common class for unittesting writers.'''
def prepareTest(self, policy_json, grd_text):
'''Parses a grit tree along with a data structure of policies.
Args:
policy_json: The policy data structure in JSON format.
grd_text: The grit tree in text form.
'''
tmp_file_name = 'test.json'
tmp_dir_name = tempfile.gettempdir()
json_file_path = tmp_dir_name + '/' + tmp_file_name
f = open(json_file_path, 'w')
f.write(policy_json.strip())
f.close()
grd = grd_reader.Parse(
StringIO.StringIO(grd_text % json_file_path), dir=tmp_dir_name)
grd.RunGatherers(recursive=True)
os.unlink(json_file_path)
return grd
def CompareResult(self, grd, env_lang, env_defs, out_type, out_lang,
expected_output):
'''Generates an output of the writer and compares it with the expected
result. Fails if they differ.
Args:
grd: The root of the grit tree.
env_lang: The environment language.
env_defs: Environment definitions.
out_type: Type of the output node for which output will be generated.
out_lang: Language of the output node for which output will be generated.
expected_output: The expected output of the writer.
'''
grd.SetOutputContext(env_lang, env_defs)
buf = StringIO.StringIO()
build.RcBuilder.ProcessNode(grd, DummyOutput(out_type, out_lang), buf)
output = buf.getvalue()
self.assertEquals(output.strip(), expected_output.strip())
...@@ -250,7 +250,7 @@ class GritNode(base.Node): ...@@ -250,7 +250,7 @@ class GritNode(base.Node):
elif t == 'js_map_format': elif t == 'js_map_format':
from grit.format import js_map_format from grit.format import js_map_format
return js_map_format.TopLevel() return js_map_format.TopLevel()
elif t == 'adm': elif t in ['adm', 'plist', 'plist_strings']:
from grit.format.policy_templates import template_formatter from grit.format.policy_templates import template_formatter
return template_formatter.TemplateFormatter(t) return template_formatter.TemplateFormatter(t)
else: else:
......
...@@ -47,6 +47,9 @@ class TestSuiteAll(unittest.TestSuite): ...@@ -47,6 +47,9 @@ class TestSuiteAll(unittest.TestSuite):
from grit.node.custom import filename_unittest from grit.node.custom import filename_unittest
import grit.format.js_map_format_unittest import grit.format.js_map_format_unittest
from grit.format.policy_templates import policy_template_generator_unittest from grit.format.policy_templates import policy_template_generator_unittest
from grit.format.policy_templates.writers import plist_writer_unittest
from grit.format.policy_templates.writers \
import plist_strings_writer_unittest
test_classes = [ test_classes = [
base_unittest.NodeUnittest, base_unittest.NodeUnittest,
...@@ -77,6 +80,8 @@ class TestSuiteAll(unittest.TestSuite): ...@@ -77,6 +80,8 @@ class TestSuiteAll(unittest.TestSuite):
filename_unittest.WindowsFilenameUnittest, filename_unittest.WindowsFilenameUnittest,
grit.format.js_map_format_unittest.JsMapFormatUnittest, grit.format.js_map_format_unittest.JsMapFormatUnittest,
policy_template_generator_unittest.PolicyTemplateGeneratorUnittest, policy_template_generator_unittest.PolicyTemplateGeneratorUnittest,
plist_writer_unittest.PListWriterUnittest,
plist_strings_writer_unittest.PListStringsWriterUnittest,
# add test classes here... # add test classes here...
] ]
......
...@@ -182,7 +182,7 @@ are exported to translation interchange files (e.g. XMB files), etc. ...@@ -182,7 +182,7 @@ are exported to translation interchange files (e.g. XMB files), etc.
if output.GetType() in ('rc_header', 'resource_map_header', if output.GetType() in ('rc_header', 'resource_map_header',
'resource_map_source', 'resource_file_map_source'): 'resource_map_source', 'resource_file_map_source'):
encoding = 'cp1252' encoding = 'cp1252'
elif output.GetType() == 'js_map_format': elif output.GetType() in ['js_map_format', 'plist', 'plist_strings']:
encoding = 'utf_8' encoding = 'utf_8'
else: else:
# TODO(gfeher) modify here to set utf-8 encoding for admx/adml # TODO(gfeher) modify here to set utf-8 encoding for admx/adml
......
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