aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2014-04-10 11:53:13 +0100
committerBen Murdoch <benm@google.com>2014-04-10 11:53:13 +0100
commit790a254225fcf929fd6659323c1455dbd1167624 (patch)
tree2346d58f8a1c83d83320e5fe103037d04b0a5658
parentb9e867e779e33cb8710a262e84b289e93e8fa3fa (diff)
parentfc300288d9f8b8f795aa8131cd0ab5f4cec154a4 (diff)
downloadgrit-790a254225fcf929fd6659323c1455dbd1167624.tar.gz
Merge from Chromium at DEPS revision 262940
This commit was generated by merge_to_master.py. Change-Id: I3590ff6b9511207e7c3fe2b8ae6eaa8e11342642
-rwxr-xr-xgrit/format/data_pack.py113
-rw-r--r--grit/format/data_pack_unittest.py29
-rw-r--r--grit/format/policy_templates/policy_template_generator.py17
-rw-r--r--grit/format/policy_templates/writers/adml_writer_unittest.py2
-rw-r--r--grit/format/policy_templates/writers/admx_writer_unittest.py2
-rw-r--r--grit/format/policy_templates/writers/doc_writer.py63
-rw-r--r--grit/format/policy_templates/writers/ios_plist_writer.py122
-rw-r--r--grit/format/policy_templates/writers/ios_plist_writer_unittest.py208
-rw-r--r--grit/format/policy_templates/writers/json_writer.py24
-rw-r--r--grit/format/policy_templates/writers/json_writer_unittest.py12
-rw-r--r--grit/format/policy_templates/writers/plist_writer.py7
-rw-r--r--grit/format/policy_templates/writers/reg_writer.py11
-rw-r--r--grit/format/policy_templates/writers/reg_writer_unittest.py12
-rw-r--r--grit/format/policy_templates/writers/xml_formatted_writer.py8
-rwxr-xr-xgrit/format/repack.py22
-rw-r--r--grit/test_suite_all.py9
-rw-r--r--grit/tool/build.py6
17 files changed, 524 insertions, 143 deletions
diff --git a/grit/format/data_pack.py b/grit/format/data_pack.py
index 0cdbbd8..779a862 100755
--- a/grit/format/data_pack.py
+++ b/grit/format/data_pack.py
@@ -3,9 +3,9 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-'''Support for formatting a data pack file used for platform agnostic resource
+"""Support for formatting a data pack file used for platform agnostic resource
files.
-'''
+"""
import collections
import exceptions
@@ -19,7 +19,6 @@ from grit import util
from grit.node import include
from grit.node import message
from grit.node import structure
-from grit.node import misc
PACK_FILE_VERSION = 4
@@ -37,7 +36,7 @@ DataPackContents = collections.namedtuple(
def Format(root, lang='en', output_dir='.'):
- '''Writes out the data pack file format (platform agnostic resource file).'''
+ """Writes out the data pack file format (platform agnostic resource file)."""
data = {}
for node in root.ActiveDescendants():
with node:
@@ -55,9 +54,9 @@ def ReadDataPack(input_file):
original_data = data
# Read the header.
- version, num_entries, encoding = struct.unpack("<IIB", data[:HEADER_LENGTH])
+ version, num_entries, encoding = struct.unpack('<IIB', data[:HEADER_LENGTH])
if version != PACK_FILE_VERSION:
- print "Wrong file version in ", input_file
+ print 'Wrong file version in ', input_file
raise WrongFileVersion
resources = {}
@@ -68,22 +67,21 @@ def ReadDataPack(input_file):
data = data[HEADER_LENGTH:]
kIndexEntrySize = 2 + 4 # Each entry is a uint16 and a uint32.
for _ in range(num_entries):
- id, offset = struct.unpack("<HI", data[:kIndexEntrySize])
+ id, offset = struct.unpack('<HI', data[:kIndexEntrySize])
data = data[kIndexEntrySize:]
- next_id, next_offset = struct.unpack("<HI", data[:kIndexEntrySize])
+ next_id, next_offset = struct.unpack('<HI', data[:kIndexEntrySize])
resources[id] = original_data[offset:next_offset]
return DataPackContents(resources, encoding)
def WriteDataPackToString(resources, encoding):
- """Write a map of id=>data into a string in the data pack format and return
- it."""
+ """Returns a string with a map of id=>data in the data pack format."""
ids = sorted(resources.keys())
ret = []
# Write file header.
- ret.append(struct.pack("<IIB", PACK_FILE_VERSION, len(ids), encoding))
+ ret.append(struct.pack('<IIB', PACK_FILE_VERSION, len(ids), encoding))
HEADER_LENGTH = 2 * 4 + 1 # Two uint32s and one uint8.
# Each entry is a uint16 + a uint32s. We have one extra entry for the last
@@ -93,10 +91,10 @@ def WriteDataPackToString(resources, encoding):
# Write index.
data_offset = HEADER_LENGTH + index_length
for id in ids:
- ret.append(struct.pack("<HI", id, data_offset))
+ ret.append(struct.pack('<HI', id, data_offset))
data_offset += len(resources[id])
- ret.append(struct.pack("<HI", 0, data_offset))
+ ret.append(struct.pack('<HI', 0, data_offset))
# Write data.
for id in ids:
@@ -105,39 +103,78 @@ def WriteDataPackToString(resources, encoding):
def WriteDataPack(resources, output_file, encoding):
- """Write a map of id=>data into output_file as a data pack."""
+ """Writes a map of id=>data into output_file as a data pack."""
content = WriteDataPackToString(resources, encoding)
- with open(output_file, "wb") as file:
+ with open(output_file, 'wb') as file:
file.write(content)
-def RePack(output_file, input_files):
- """Write a new data pack to |output_file| based on a list of filenames
- (|input_files|)"""
+def RePack(output_file, input_files, whitelist_file=None):
+ """Write a new data pack file by combining input pack files.
+
+ Args:
+ output_file: path to the new data pack file.
+ input_files: a list of paths to the data pack files to combine.
+ whitelist_file: path to the file that contains the list of resource IDs
+ that should be kept in the output file or None to include
+ all resources.
+
+ Raises:
+ KeyError: if there are duplicate keys or resource encoding is
+ inconsistent.
+ """
+ input_data_packs = [ReadDataPack(filename) for filename in input_files]
+ whitelist = None
+ if whitelist_file:
+ whitelist = util.ReadFile(whitelist_file, util.RAW_TEXT).strip().split('\n')
+ whitelist = map(int, whitelist)
+ resources, encoding = RePackFromDataPackStrings(input_data_packs, whitelist)
+ WriteDataPack(resources, output_file, encoding)
+
+
+def RePackFromDataPackStrings(inputs, whitelist):
+ """Returns a data pack string that combines the resources from inputs.
+
+ Args:
+ inputs: a list of data pack strings that need to be combined.
+ whitelist: a list of resource IDs that should be kep in the output string
+ or None to include all resources.
+
+ Returns:
+ DataPackContents: a tuple containing the new combined data pack and its
+ encoding.
+
+ Raises:
+ KeyError: if there are duplicate keys or resource encoding is
+ inconsistent.
+ """
resources = {}
encoding = None
- for filename in input_files:
- new_content = ReadDataPack(filename)
-
+ for content in inputs:
# Make sure we have no dups.
- duplicate_keys = set(new_content.resources.keys()) & set(resources.keys())
- if len(duplicate_keys) != 0:
- raise exceptions.KeyError("Duplicate keys: " + str(list(duplicate_keys)))
+ duplicate_keys = set(content.resources.keys()) & set(resources.keys())
+ if duplicate_keys:
+ raise exceptions.KeyError('Duplicate keys: ' + str(list(duplicate_keys)))
# Make sure encoding is consistent.
if encoding in (None, BINARY):
- encoding = new_content.encoding
- elif new_content.encoding not in (BINARY, encoding):
- raise exceptions.KeyError("Inconsistent encodings: " +
- str(encoding) + " vs " +
- str(new_content.encoding))
-
- resources.update(new_content.resources)
+ encoding = content.encoding
+ elif content.encoding not in (BINARY, encoding):
+ raise exceptions.KeyError('Inconsistent encodings: ' + str(encoding) +
+ ' vs ' + str(content.encoding))
+
+ if whitelist:
+ whitelisted_resources = dict([(key, content.resources[key])
+ for key in content.resources.keys()
+ if key in whitelist])
+ resources.update(whitelisted_resources)
+ else:
+ resources.update(content.resources)
# Encoding is 0 for BINARY, 1 for UTF8 and 2 for UTF16
if encoding is None:
encoding = BINARY
- WriteDataPack(resources, output_file, encoding)
+ return DataPackContents(resources, encoding)
# Temporary hack for external programs that import data_pack.
@@ -157,14 +194,14 @@ def main():
data = ReadDataPack(sys.argv[1])
print data.encoding
for (resource_id, text) in data.resources.iteritems():
- print "%s: %s" % (resource_id, text)
+ print '%s: %s' % (resource_id, text)
else:
# Just write a simple file.
- data = { 1: "", 4: "this is id 4", 6: "this is id 6", 10: "" }
- WriteDataPack(data, "datapack1.pak", UTF8)
- data2 = { 1000: "test", 5: "five" }
- WriteDataPack(data2, "datapack2.pak", UTF8)
- print "wrote datapack1 and datapack2 to current directory."
+ data = {1: '', 4: 'this is id 4', 6: 'this is id 6', 10: ''}
+ WriteDataPack(data, 'datapack1.pak', UTF8)
+ data2 = {1000: 'test', 5: 'five'}
+ WriteDataPack(data2, 'datapack2.pak', UTF8)
+ print 'wrote datapack1 and datapack2 to current directory.'
if __name__ == '__main__':
diff --git a/grit/format/data_pack_unittest.py b/grit/format/data_pack_unittest.py
index d210c99..f6e9edc 100644
--- a/grit/format/data_pack_unittest.py
+++ b/grit/format/data_pack_unittest.py
@@ -28,10 +28,37 @@ class FormatDataPackUnittest(unittest.TestCase):
'\x0a\x00\x3f\x00\x00\x00' # index entry 10
'\x00\x00\x3f\x00\x00\x00' # extra entry for the size of last
'this is id 4this is id 6') # data
- input = { 1: "", 4: "this is id 4", 6: "this is id 6", 10: "" }
+ input = {1: '', 4: 'this is id 4', 6: 'this is id 6', 10: ''}
output = data_pack.WriteDataPackToString(input, data_pack.UTF8)
self.failUnless(output == expected)
+ def testRePackUnittest(self):
+ expected_with_whitelist = {
+ 1: 'Never gonna', 10: 'give you up', 20: 'Never gonna let',
+ 30: 'you down', 40: 'Never', 50: 'gonna run around and',
+ 60: 'desert you'}
+ expected_without_whitelist = {
+ 1: 'Never gonna', 10: 'give you up', 20: 'Never gonna let', 65: 'Close',
+ 30: 'you down', 40: 'Never', 50: 'gonna run around and', 4: 'click',
+ 60: 'desert you', 6: 'chirr', 32: 'oops, try again', 70: 'Awww, snap!'}
+ inputs = [{1: 'Never gonna', 4: 'click', 6: 'chirr', 10: 'give you up'},
+ {20: 'Never gonna let', 30: 'you down', 32: 'oops, try again'},
+ {40: 'Never', 50: 'gonna run around and', 60: 'desert you'},
+ {65: 'Close', 70: 'Awww, snap!'}]
+ whitelist = [1, 10, 20, 30, 40, 50, 60]
+ inputs = [data_pack.DataPackContents(input, data_pack.UTF8) for input
+ in inputs]
+
+ # RePack using whitelist
+ output, _ = data_pack.RePackFromDataPackStrings(inputs, whitelist)
+ self.assertDictEqual(expected_with_whitelist, output,
+ 'Incorrect resource output')
+
+ # RePack a None whitelist
+ output, _ = data_pack.RePackFromDataPackStrings(inputs, None)
+ self.assertDictEqual(expected_without_whitelist, output,
+ 'Incorrect resource output')
+
if __name__ == '__main__':
unittest.main()
diff --git a/grit/format/policy_templates/policy_template_generator.py b/grit/format/policy_templates/policy_template_generator.py
index 3fad8ca..11d097e 100644
--- a/grit/format/policy_templates/policy_template_generator.py
+++ b/grit/format/policy_templates/policy_template_generator.py
@@ -5,7 +5,6 @@
import copy
-import types
class PolicyTemplateGenerator:
@@ -104,20 +103,6 @@ class PolicyTemplateGenerator:
})
return result
- def _PrintPolicyValue(self, item):
- '''Produces a string representation for a policy value. Taking care to print
- dictionaries in a sorted order.'''
- if type(item) == types.StringType:
- str_val = "'%s'" % item
- elif isinstance(item, dict):
- str_val = "{";
- for it in sorted(item.iterkeys()):
- str_val += "\'%s\': %s, " % (it, self._PrintPolicyValue(item[it]))
- str_val = str_val.rstrip(", ") + "}";
- else:
- str_val = str(item)
- return str_val;
-
def _ProcessPolicy(self, policy):
'''Processes localized message strings in a policy or a group.
Also breaks up the content of 'supported_on' attribute into a list.
@@ -137,8 +122,6 @@ class PolicyTemplateGenerator:
# Iterate through all the items of an enum-type policy, and add captions.
for item in policy['items']:
item['caption'] = self._ImportMessage(item['caption'])
- elif policy['type'] == 'dict' and 'example_value' in policy:
- policy['example_value'] = self._PrintPolicyValue(policy['example_value'])
if policy['type'] != 'group':
if not 'label' in policy:
# If 'label' is not specified, then it defaults to 'caption':
diff --git a/grit/format/policy_templates/writers/adml_writer_unittest.py b/grit/format/policy_templates/writers/adml_writer_unittest.py
index 41757d9..3600005 100644
--- a/grit/format/policy_templates/writers/adml_writer_unittest.py
+++ b/grit/format/policy_templates/writers/adml_writer_unittest.py
@@ -18,7 +18,7 @@ from grit.format.policy_templates.writers import adml_writer
from grit.format.policy_templates.writers import xml_writer_base_unittest
-class AdmlWriterTest(xml_writer_base_unittest.XmlWriterBaseTest):
+class AdmlWriterUnittest(xml_writer_base_unittest.XmlWriterBaseTest):
def setUp(self):
config = {
diff --git a/grit/format/policy_templates/writers/admx_writer_unittest.py b/grit/format/policy_templates/writers/admx_writer_unittest.py
index 9a2a58e..c99131f 100644
--- a/grit/format/policy_templates/writers/admx_writer_unittest.py
+++ b/grit/format/policy_templates/writers/admx_writer_unittest.py
@@ -19,7 +19,7 @@ from grit.format.policy_templates.writers import xml_writer_base_unittest
from xml.dom import minidom
-class AdmxWriterTest(xml_writer_base_unittest.XmlWriterBaseTest):
+class AdmxWriterUnittest(xml_writer_base_unittest.XmlWriterBaseTest):
def _CreateDocumentElement(self):
dom_impl = minidom.getDOMImplementation('')
diff --git a/grit/format/policy_templates/writers/doc_writer.py b/grit/format/policy_templates/writers/doc_writer.py
index ee45cd5..7cca976 100644
--- a/grit/format/policy_templates/writers/doc_writer.py
+++ b/grit/format/policy_templates/writers/doc_writer.py
@@ -234,41 +234,32 @@ class DocWriter(xml_formatted_writer.XMLFormattedWriter):
if self.IsPolicySupportedOnPlatform(policy, 'mac'):
self._AddListExampleMac(examples, policy)
- def _PythonDictionaryToMacDictionary(self, dictionary, indent=''):
- '''Converts a python dictionary to an equivalent XML plist.
-
- Returns a list of lines, with one dictionary entry per line.'''
- result = [indent + '<dict>']
- indent += ' '
- for k in sorted(dictionary.keys()):
- v = dictionary[k]
- result.append('%s<key>%s</key>' % (indent, k))
- value_type = type(v)
- if value_type == bool:
- result.append('%s<%s/>' % (indent, 'true' if v else 'false'))
- elif value_type == int:
- result.append('%s<integer>%s</integer>' % (indent, v))
- elif value_type == str:
- result.append('%s<string>%s</string>' % (indent, v))
- elif value_type == dict:
- result += self._PythonDictionaryToMacDictionary(v, indent)
- elif value_type == list:
- array = []
- if len(v) != 0:
- if type(v[0]) == str:
- array = ['%s <string>%s</string>' % (indent, x) for x in v]
- elif type(v[0]) == dict:
- for x in v:
- array += self._PythonDictionaryToMacDictionary(x, indent + ' ')
- else:
- raise Exception('Must be list of string or dict.')
- result.append('%s<array>' % indent)
- result += array
- result.append('%s</array>' % indent)
- else:
- raise Exception('Invalid example value type %s' % value_type)
- result.append(indent[2:] + '</dict>')
- return result
+ def _PythonObjectToPlist(self, obj, indent=''):
+ '''Converts a python object to an equivalent XML plist.
+
+ Returns a list of lines.'''
+ obj_type = type(obj)
+ if obj_type == bool:
+ return [ '%s<%s/>' % (indent, 'true' if obj else 'false') ]
+ elif obj_type == int:
+ return [ '%s<integer>%s</integer>' % (indent, obj) ]
+ elif obj_type == str:
+ return [ '%s<string>%s</string>' % (indent, obj) ]
+ elif obj_type == list:
+ result = [ '%s<array>' % indent ]
+ for item in obj:
+ result += self._PythonObjectToPlist(item, indent + ' ')
+ result.append('%s</array>' % indent)
+ return result
+ elif obj_type == dict:
+ result = [ '%s<dict>' % indent ]
+ for key in sorted(obj.keys()):
+ result.append('%s<key>%s</key>' % (indent + ' ', key))
+ result += self._PythonObjectToPlist(obj[key], indent + ' ')
+ result.append('%s</dict>' % indent)
+ return result
+ else:
+ raise Exception('Invalid object to convert: %s' % obj)
def _AddDictionaryExampleMac(self, parent, policy):
'''Adds an example value for Mac of a 'dict' policy to a DOM node.
@@ -282,7 +273,7 @@ class DocWriter(xml_formatted_writer.XMLFormattedWriter):
self.AddElement(parent, 'dt', {}, 'Mac:')
mac = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre'])
mac_text = ['<key>%s</key>' % (policy['name'])]
- mac_text += self._PythonDictionaryToMacDictionary(example_value)
+ mac_text += self._PythonObjectToPlist(example_value)
self.AddText(mac, '\n'.join(mac_text))
def _AddDictionaryExampleWindows(self, parent, policy):
diff --git a/grit/format/policy_templates/writers/ios_plist_writer.py b/grit/format/policy_templates/writers/ios_plist_writer.py
new file mode 100644
index 0000000..1da64aa
--- /dev/null
+++ b/grit/format/policy_templates/writers/ios_plist_writer.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 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 base64
+
+from xml.dom import minidom
+from grit.format.policy_templates.writers import plist_writer
+
+
+# This writer outputs a Property List with an example for each of the policies
+# supported on iOS. This plist can be pushed to Chrome on iOS via the MDM API
+# introduced in iOS 7.
+
+CHROME_POLICY_COMMENT = '''\
+ ChromePolicy is the preferred key to configure Chrome.
+ Each of the keys in this <dict> configures a Chrome policy.
+ All of the Chrome policies are configured with an example
+ value below.
+ Note that it's not necessary to configure all of them. '''
+
+ENCODED_CHROME_POLICY_COMMENT = '''\
+ EncodedChromePolicy contains a Property List file, encoded in Base64,
+ which contains the same policies that can go in ChromePolicy.
+ This key can be used by vendors that restrict the app configuration
+ types to strings.
+ The value of this string can be validated by running these
+ commands in Mac OS X:
+
+ # (first, copy-paste the string into a file named "policy.plist")
+ # base64 -D < policy.plist > decoded_policy.plist
+ # plutil -lint decoded_policy.plist
+
+ plutil should indicate that decoded_policy.plist is valid,
+ otherwise Chrome will reject the encoded string too.
+
+ This command can be used to pretty-print the plist file:
+
+ # plutil -convert xml1 decoded_policy.plist
+
+ Note that <ChromePolicy> is the preferred key to configure Chrome.
+ If <ChromePolicy> is present then <EncodedChromePolicy> is ignored. '''
+
+def GetWriter(config):
+ '''Factory method for creating IOSPlistWriter objects.
+ See the constructor of TemplateWriter for description of
+ arguments.
+ '''
+ return IOSPlistWriter(['ios'], config)
+
+
+class IOSPlistWriter(plist_writer.PListWriter):
+ '''Class for generating policy templates in the iOS plist format.
+ It is used by PolicyTemplateGenerator to write plist files.
+ '''
+
+ # Overridden.
+ def IsPolicySupported(self, policy):
+ # Output examples only for policies that are supported on iOS.
+ for support_on in policy['supported_on']:
+ if ('ios' in support_on['platforms'] and
+ support_on['until_version'] == '' and
+ super(IOSPlistWriter, self).IsPolicySupported(policy)):
+ return True
+ return False
+
+ def _WriteValue(self, parent, value):
+ if type(value) == bool:
+ self.AddElement(parent, 'true' if value else 'false')
+ elif type(value) == int:
+ self.AddElement(parent, 'integer', {}, str(value))
+ elif type(value) == str:
+ self.AddElement(parent, 'string', {}, value)
+ elif type(value) == list:
+ array = self.AddElement(parent, 'array')
+ for element in value:
+ self._WriteValue(array, element)
+ elif type(value) == dict:
+ dic = self.AddElement(parent, 'dict')
+ for k, v in sorted(value.iteritems()):
+ self.AddElement(dic, 'key', {}, k)
+ self._WriteValue(dic, v)
+ else:
+ raise ValueError('Unsupported type in example value: ' + type(value))
+
+ # Overridden.
+ def WritePolicy(self, policy):
+ for dict in [self._dict, self._encoded_dict]:
+ self.AddElement(dict, 'key', {}, policy['name'])
+ self._WriteValue(dict, policy['example_value'])
+
+ # Overridden.
+ # |self._plist| is created in super.Init().
+ def BeginTemplate(self):
+ self._plist.attributes['version'] = '1.0'
+ self._root_dict = self.AddElement(self._plist, 'dict')
+ self.AddComment(self._root_dict, CHROME_POLICY_COMMENT)
+ self._dict = self._AddKeyValuePair(self._root_dict, 'ChromePolicy', 'dict')
+
+ self._encoded_plist.attributes['version'] = '1.0'
+ self._encoded_dict = self.AddElement(self._encoded_plist, 'dict')
+
+ # Overridden.
+ def EndTemplate(self):
+ # Add the "EncodedChromePolicy" entry.
+ encoded = base64.b64encode(self._encoded_doc.toxml())
+ self.AddComment(self._root_dict, ENCODED_CHROME_POLICY_COMMENT)
+ self._AddStringKeyValuePair(self._root_dict, 'EncodedChromePolicy', encoded)
+
+ # Overridden.
+ def Init(self):
+ super(IOSPlistWriter, self).Init()
+ # Create a secondary DOM for the EncodedChromePolicy Plist, which will be
+ # serialized and encoded in EndTemplate.
+ self._encoded_doc = self.CreatePlistDocument()
+ self._encoded_plist = self._encoded_doc.documentElement
+
+ # Overridden.
+ def GetTemplateText(self):
+ return self.ToPrettyXml(self._doc, encoding='UTF-8')
diff --git a/grit/format/policy_templates/writers/ios_plist_writer_unittest.py b/grit/format/policy_templates/writers/ios_plist_writer_unittest.py
new file mode 100644
index 0000000..14a0cab
--- /dev/null
+++ b/grit/format/policy_templates/writers/ios_plist_writer_unittest.py
@@ -0,0 +1,208 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 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.ios_plist_writer'''
+
+
+import base64
+import functools
+import os
+import plistlib
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
+
+import unittest
+
+try:
+ import Cocoa
+except:
+ Cocoa = None
+
+from grit.format.policy_templates.writers import writer_unittest_common
+
+
+class IOSPListWriterUnittest(writer_unittest_common.WriterUnittestCommon):
+ '''Unit tests for IOSPListWriter.'''
+
+ def _ParseWithPython(self, decode, text):
+ '''Parses a serialized Plist, using Python's plistlib.
+
+ If |decode| is true then |text| is decoded as Base64 before being
+ deserialized as a Plist.'''
+ if decode:
+ text = base64.b64decode(text)
+ return plistlib.readPlistFromString(text)
+
+ def _ParseWithCocoa(self, decode, text):
+ '''Parses a serialized Plist, using Cocoa's python bindings.
+
+ If |decode| is true then |text| is decoded as Base64 before being
+ deserialized as a Plist.'''
+ if decode:
+ data = Cocoa.NSData.alloc().initWithBase64EncodedString_options_(text, 0)
+ else:
+ data = Cocoa.NSData.alloc().initWithBytes_length_(text, len(text))
+ result = Cocoa.NSPropertyListSerialization. \
+ propertyListFromData_mutabilityOption_format_errorDescription_(
+ data, Cocoa.NSPropertyListImmutable, None, None)
+ return result[0]
+
+ def _VerifyGeneratedOutputWithParsers(self,
+ templates,
+ expected_output,
+ parse,
+ decode_and_parse):
+ # Generate the grit output for |templates|.
+ output = self.GetOutput(
+ self.PrepareTest(templates),
+ 'fr',
+ { '_chromium': '1', 'mac_bundle_id': 'com.example.Test' },
+ 'ios_plist',
+ 'en')
+
+ # Parse it as a Plist.
+ plist = parse(output)
+ self.assertEquals(len(plist), 2)
+ self.assertTrue('ChromePolicy' in plist)
+ self.assertTrue('EncodedChromePolicy' in plist)
+
+ # Get the 2 expected fields.
+ chrome_policy = plist['ChromePolicy']
+ encoded_chrome_policy = plist['EncodedChromePolicy']
+
+ # Verify the ChromePolicy.
+ self.assertEquals(chrome_policy, expected_output)
+
+ # Decode the EncodedChromePolicy and verify it.
+ decoded_chrome_policy = decode_and_parse(encoded_chrome_policy)
+ self.assertEquals(decoded_chrome_policy, expected_output)
+
+ def _VerifyGeneratedOutput(self, templates, expected):
+ # plistlib is available on all Python platforms.
+ parse = functools.partial(self._ParseWithPython, False)
+ decode_and_parse = functools.partial(self._ParseWithPython, True)
+ self._VerifyGeneratedOutputWithParsers(
+ templates, expected, parse, decode_and_parse)
+
+ # The Cocoa bindings are available on Mac OS X only.
+ if Cocoa:
+ parse = functools.partial(self._ParseWithCocoa, False)
+ decode_and_parse = functools.partial(self._ParseWithCocoa, True)
+ self._VerifyGeneratedOutputWithParsers(
+ templates, expected, parse, decode_and_parse)
+
+ def _MakeTemplate(self, name, type, example, extra=''):
+ return '''
+ {
+ 'policy_definitions': [
+ {
+ 'name': '%s',
+ 'type': '%s',
+ 'desc': '',
+ 'caption': '',
+ 'supported_on': ['ios:35-'],
+ 'example_value': %s,
+ %s
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {},
+ }
+ ''' % (name, type, example, extra)
+
+ def testEmpty(self):
+ templates = '''
+ {
+ 'policy_definitions': [],
+ 'placeholders': [],
+ 'messages': {},
+ }
+ '''
+ expected = {}
+ self._VerifyGeneratedOutput(templates, expected)
+
+ def testBoolean(self):
+ templates = self._MakeTemplate('BooleanPolicy', 'main', 'True')
+ expected = {
+ 'BooleanPolicy': True,
+ }
+ self._VerifyGeneratedOutput(templates, expected)
+
+ def testString(self):
+ templates = self._MakeTemplate('StringPolicy', 'string', '"Foo"')
+ expected = {
+ 'StringPolicy': 'Foo',
+ }
+ self._VerifyGeneratedOutput(templates, expected)
+
+ def testStringEnum(self):
+ templates = self._MakeTemplate(
+ 'StringEnumPolicy', 'string-enum', '"Foo"',
+ '''
+ 'items': [
+ { 'name': 'Foo', 'value': 'Foo', 'caption': '' },
+ { 'name': 'Bar', 'value': 'Bar', 'caption': '' },
+ ],
+ ''')
+ expected = {
+ 'StringEnumPolicy': 'Foo',
+ }
+ self._VerifyGeneratedOutput(templates, expected)
+
+ def testInt(self):
+ templates = self._MakeTemplate('IntPolicy', 'int', '42')
+ expected = {
+ 'IntPolicy': 42,
+ }
+ self._VerifyGeneratedOutput(templates, expected)
+
+ def testIntEnum(self):
+ templates = self._MakeTemplate(
+ 'IntEnumPolicy', 'int-enum', '42',
+ '''
+ 'items': [
+ { 'name': 'Foo', 'value': 100, 'caption': '' },
+ { 'name': 'Bar', 'value': 42, 'caption': '' },
+ ],
+ ''')
+ expected = {
+ 'IntEnumPolicy': 42,
+ }
+ self._VerifyGeneratedOutput(templates, expected)
+
+ def testStringList(self):
+ templates = self._MakeTemplate('StringListPolicy', 'list', '["a", "b"]')
+ expected = {
+ 'StringListPolicy': [ "a", "b" ],
+ }
+ self._VerifyGeneratedOutput(templates, expected)
+
+ def testListOfDictionary(self):
+ templates = self._MakeTemplate(
+ 'ManagedBookmarks', 'dict',
+ '''
+ [
+ {
+ "name": "Google Search",
+ "url": "www.google.com",
+ },
+ {
+ "name": "Youtube",
+ "url": "www.youtube.com",
+ }
+ ]
+ ''')
+ expected = {
+ 'ManagedBookmarks': [
+ { "name": "Google Search", "url": "www.google.com" },
+ { "name": "Youtube", "url": "www.youtube.com" },
+ ],
+ }
+ self._VerifyGeneratedOutput(templates, expected)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/grit/format/policy_templates/writers/json_writer.py b/grit/format/policy_templates/writers/json_writer.py
index 4739483..673bbf7 100644
--- a/grit/format/policy_templates/writers/json_writer.py
+++ b/grit/format/policy_templates/writers/json_writer.py
@@ -3,6 +3,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import json
+
from textwrap import TextWrapper
from grit.format.policy_templates.writers import template_writer
@@ -38,28 +40,10 @@ class JsonWriter(template_writer.TemplateWriter):
return self.FlattenGroupsAndSortPolicies(policy_list)
def WritePolicy(self, policy):
- example_value = policy['example_value']
- if policy['type'] == 'string':
- example_value_str = '"' + example_value + '"'
- elif policy['type'] in ('int', 'int-enum', 'dict'):
- example_value_str = str(example_value)
- elif policy['type'] == 'list':
- if example_value == []:
- example_value_str = '[]'
- else:
- example_value_str = '["%s"]' % '", "'.join(example_value)
- elif policy['type'] == 'main':
- if example_value == True:
- example_value_str = 'true'
- else:
- example_value_str = 'false'
- elif policy['type'] == 'string-enum':
- example_value_str = '"%s"' % example_value;
- elif policy['type'] == 'external':
+ if policy['type'] == 'external':
# This type can only be set through cloud policy.
return
- else:
- raise Exception('unknown policy type %s:' % policy['type'])
+ example_value_str = json.dumps(policy['example_value'], sort_keys=True)
# Add comma to the end of the previous line.
if not self._first_written:
diff --git a/grit/format/policy_templates/writers/json_writer_unittest.py b/grit/format/policy_templates/writers/json_writer_unittest.py
index 1281c19..00acde3 100644
--- a/grit/format/policy_templates/writers/json_writer_unittest.py
+++ b/grit/format/policy_templates/writers/json_writer_unittest.py
@@ -235,13 +235,13 @@ class JsonWriterUnittest(writer_unittest_common.WriterUnittestCommon):
# Tests a policy group with a single policy of type 'dict'.
example = {
'bool': True,
- 'int': 10,
- 'string': 'abc',
- 'list': [1, 2, 3],
'dict': {
'a': 1,
'b': 2,
- }
+ },
+ 'int': 10,
+ 'list': [1, 2, 3],
+ 'string': 'abc',
}
grd = self.PrepareTest(
'{'
@@ -264,8 +264,8 @@ class JsonWriterUnittest(writer_unittest_common.WriterUnittestCommon):
' // Example Dictionary Policy\n' +
HEADER_DELIMETER +
' // Example Dictionary Policy\n\n'
- ' //"DictionaryPolicy": {\'bool\': True, \'dict\': {\'a\': 1, '
- '\'b\': 2}, \'int\': 10, \'list\': [1, 2, 3], \'string\': \'abc\'}\n\n'
+ ' //"DictionaryPolicy": {"bool": true, "dict": {"a": 1, '
+ '"b": 2}, "int": 10, "list": [1, 2, 3], "string": "abc"}\n\n'
'}')
self.CompareOutputs(output, expected_output)
diff --git a/grit/format/policy_templates/writers/plist_writer.py b/grit/format/policy_templates/writers/plist_writer.py
index 46b7ade..2297858 100644
--- a/grit/format/policy_templates/writers/plist_writer.py
+++ b/grit/format/policy_templates/writers/plist_writer.py
@@ -127,13 +127,16 @@ class PListWriter(xml_formatted_writer.XMLFormattedWriter):
self._array = self._AddKeyValuePair(dict, 'pfm_subkeys', 'array')
- def Init(self):
+ def CreatePlistDocument(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)
+ return dom_impl.createDocument(None, 'plist', doctype)
+
+ def Init(self):
+ self._doc = self.CreatePlistDocument()
self._plist = self._doc.documentElement
def GetTemplateText(self):
diff --git a/grit/format/policy_templates/writers/reg_writer.py b/grit/format/policy_templates/writers/reg_writer.py
index 716cd74..beb1590 100644
--- a/grit/format/policy_templates/writers/reg_writer.py
+++ b/grit/format/policy_templates/writers/reg_writer.py
@@ -4,6 +4,8 @@
# found in the LICENSE file.
+import json
+
from grit.format.policy_templates.writers import template_writer
@@ -64,9 +66,10 @@ class RegWriter(template_writer.TemplateWriter):
i = i + 1
else:
self._StartBlock(key, None, list)
- if policy['type'] in ('string', 'dict'):
- escaped_str = self._EscapeRegString(str(example_value))
- example_value_str = '"' + escaped_str + '"'
+ if policy['type'] in ('string', 'string-enum', 'dict'):
+ example_value_str = json.dumps(example_value, sort_keys=True)
+ if policy['type'] == 'dict':
+ example_value_str = '"%s"' % example_value_str
elif policy['type'] == 'main':
if example_value == True:
example_value_str = 'dword:00000001'
@@ -74,8 +77,6 @@ class RegWriter(template_writer.TemplateWriter):
example_value_str = 'dword:00000000'
elif policy['type'] in ('int', 'int-enum'):
example_value_str = 'dword:%08x' % example_value
- elif policy['type'] == 'string-enum':
- example_value_str = '"%s"' % example_value
else:
raise Exception('unknown policy type %s:' % policy['type'])
diff --git a/grit/format/policy_templates/writers/reg_writer_unittest.py b/grit/format/policy_templates/writers/reg_writer_unittest.py
index d84599c..d559c9f 100644
--- a/grit/format/policy_templates/writers/reg_writer_unittest.py
+++ b/grit/format/policy_templates/writers/reg_writer_unittest.py
@@ -216,13 +216,13 @@ class RegWriterUnittest(writer_unittest_common.WriterUnittestCommon):
# Tests a policy group with a single policy of type 'dict'.
example = {
'bool': True,
- 'int': 10,
- 'string': 'abc',
- 'list': [1, 2, 3],
'dict': {
'a': 1,
'b': 2,
- }
+ },
+ 'int': 10,
+ 'list': [1, 2, 3],
+ 'string': 'abc',
}
grd = self.PrepareTest(
'{'
@@ -244,8 +244,8 @@ class RegWriterUnittest(writer_unittest_common.WriterUnittestCommon):
'Windows Registry Editor Version 5.00',
'',
'[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium]',
- '"DictionaryPolicy"="{\'bool\': True, \'dict\': {\'a\': 1, '
- '\'b\': 2}, \'int\': 10, \'list\': [1, 2, 3], \'string\': \'abc\'}"'])
+ '"DictionaryPolicy"="{"bool": true, "dict": {"a": 1, '
+ '"b": 2}, "int": 10, "list": [1, 2, 3], "string": "abc"}"'])
self.CompareOutputs(output, expected_output)
def testNonSupportedPolicy(self):
diff --git a/grit/format/policy_templates/writers/xml_formatted_writer.py b/grit/format/policy_templates/writers/xml_formatted_writer.py
index b28d8b6..dad3717 100644
--- a/grit/format/policy_templates/writers/xml_formatted_writer.py
+++ b/grit/format/policy_templates/writers/xml_formatted_writer.py
@@ -53,7 +53,11 @@ class XMLFormattedWriter(template_writer.TemplateWriter):
attribute.value = value
parent.setAttributeNode(attribute)
- def ToPrettyXml(self, doc):
+ def AddComment(self, parent, comment):
+ '''Adds a comment node.'''
+ parent.appendChild(parent.ownerDocument.createComment(comment))
+
+ def ToPrettyXml(self, doc, **kwargs):
# return doc.toprettyxml(indent=' ')
# The above pretty-printer does not print the doctype and adds spaces
# around texts, e.g.:
@@ -66,7 +70,7 @@ class XMLFormattedWriter(template_writer.TemplateWriter):
# So we use the poor man's pretty printer here. It assumes that there are
# no mixed-content nodes.
# Get all the XML content in a one-line string.
- xml = doc.toxml()
+ xml = doc.toxml(**kwargs)
# Determine where the line breaks will be. (They will only be between tags.)
lines = xml[1:len(xml) - 1].split('><')
indent = ''
diff --git a/grit/format/repack.py b/grit/format/repack.py
index e42acdb..337b7af 100755
--- a/grit/format/repack.py
+++ b/grit/format/repack.py
@@ -9,19 +9,29 @@ http://dev.chromium.org/developers/design-documents/linuxresourcesandlocalizedst
for details about the file format.
"""
+import optparse
import os
import sys
+
if __name__ == '__main__':
sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
import grit.format.data_pack
+
def main(argv):
- if len(argv) < 3:
- print ("Usage:\n %s <output_filename> <input_file1> [input_file2] ... " %
- argv[0])
- sys.exit(-1)
- grit.format.data_pack.RePack(argv[1], argv[2:])
+ parser = optparse.OptionParser('usage: %prog [options] <output_filename>'
+ '<input_file1> [input_file2] ...')
+ parser.add_option('--whitelist', action='store', dest='whitelist',
+ default=None, help='Full path to the whitelist used to'
+ 'filter output pak file resource IDs')
+ options, file_paths = parser.parse_args(argv)
+
+ if len(file_paths) < 2:
+ parser.error('Please specify output and at least one input filenames')
+
+ grit.format.data_pack.RePack(file_paths[0], file_paths[1:],
+ whitelist_file=options.whitelist)
if '__main__' == __name__:
- main(sys.argv)
+ main(sys.argv[1:])
diff --git a/grit/test_suite_all.py b/grit/test_suite_all.py
index 3f5c978..71635fc 100644
--- a/grit/test_suite_all.py
+++ b/grit/test_suite_all.py
@@ -42,7 +42,10 @@ class TestSuiteAll(unittest.TestSuite):
import grit.format.resource_map_unittest
import grit.format.policy_templates.policy_template_generator_unittest
import grit.format.policy_templates.writers.adm_writer_unittest
+ import grit.format.policy_templates.writers.adml_writer_unittest
+ import grit.format.policy_templates.writers.admx_writer_unittest
import grit.format.policy_templates.writers.doc_writer_unittest
+ import grit.format.policy_templates.writers.ios_plist_writer_unittest
import grit.format.policy_templates.writers.json_writer_unittest
import grit.format.policy_templates.writers.plist_strings_writer_unittest
import grit.format.policy_templates.writers.plist_writer_unittest
@@ -97,8 +100,14 @@ class TestSuiteAll(unittest.TestSuite):
PolicyTemplateGeneratorUnittest,
grit.format.policy_templates.writers.adm_writer_unittest.
AdmWriterUnittest,
+ grit.format.policy_templates.writers.adml_writer_unittest.
+ AdmlWriterUnittest,
+ grit.format.policy_templates.writers.admx_writer_unittest.
+ AdmxWriterUnittest,
grit.format.policy_templates.writers.doc_writer_unittest.
DocWriterUnittest,
+ grit.format.policy_templates.writers.ios_plist_writer_unittest.
+ IOSPListWriterUnittest,
grit.format.policy_templates.writers.json_writer_unittest.
JsonWriterUnittest,
grit.format.policy_templates.writers.plist_strings_writer_unittest.
diff --git a/grit/tool/build.py b/grit/tool/build.py
index 2bb8085..87ee412 100644
--- a/grit/tool/build.py
+++ b/grit/tool/build.py
@@ -36,8 +36,10 @@ _format_modules = {
'resource_map_source': 'resource_map',
'resource_file_map_source': 'resource_map',
}
-_format_modules.update((type, 'policy_templates.template_formatter')
- for type in 'adm plist plist_strings admx adml doc json reg'.split())
+_format_modules.update(
+ (type, 'policy_templates.template_formatter') for type in
+ [ 'adm', 'admx', 'adml', 'reg', 'doc', 'json',
+ 'plist', 'plist_strings', 'ios_plist' ])
def GetFormatter(type):