diff options
author | Torne (Richard Coles) <torne@google.com> | 2014-11-06 11:12:40 +0000 |
---|---|---|
committer | Torne (Richard Coles) <torne@google.com> | 2014-11-06 11:12:40 +0000 |
commit | 0d724c494c082ea290e16211e85ffc801d5319bf (patch) | |
tree | 9a7b625bfe5d41bda8cb037eb7380ed8a72f8fba | |
parent | 06694d202087653f359acef3e1bb8325d8e2a14e (diff) | |
parent | e8e6ed4b1174a9efffaa4cad5f6bf7a440004bbe (diff) | |
download | grit-master.tar.gz |
Merge from Chromium at DEPS revision db3f05efe0f9HEADwebview-m40_r4webview-m40_r3webview-m40_r2webview-m40_r1android-m-preview-2android-m-preview-1android-m-previewub-webview-m40-releasemaster-soongmastermain
This commit was generated by merge_to_master.py.
Change-Id: I25cedbc80c8f52b759d350181e5e8ddb18a942cb
28 files changed, 876 insertions, 54 deletions
diff --git a/grit/format/policy_templates/writer_configuration.py b/grit/format/policy_templates/writer_configuration.py index 88de6b5..db9613b 100644 --- a/grit/format/policy_templates/writer_configuration.py +++ b/grit/format/policy_templates/writer_configuration.py @@ -52,6 +52,8 @@ def GetConfigurationForBuild(defines): } else: raise Exception('Unknown build') + if 'version' in defines: + config['version'] = defines['version'] config['win_group_policy_class'] = 'Both' config['win_supported_os'] = 'SUPPORTED_WINXPSP2' if 'mac_bundle_id' in defines: diff --git a/grit/format/policy_templates/writers/adm_writer.py b/grit/format/policy_templates/writers/adm_writer.py index bffbeb5..91aeef6 100644 --- a/grit/format/policy_templates/writers/adm_writer.py +++ b/grit/format/policy_templates/writers/adm_writer.py @@ -75,7 +75,12 @@ class AdmWriter(template_writer.TemplateWriter): 'dict': 'EDITTEXT' } + def _Escape(self, string): + return string.replace('.', '_') + def _AddGuiString(self, name, value): + # The |name| must be escaped. + assert name == self._Escape(name) # Escape newlines in the value. value = value.replace('\n', '\\n') if name in self.strings_seen: @@ -100,7 +105,7 @@ class AdmWriter(template_writer.TemplateWriter): key_name: The registry key backing the policy. builder: Builder to append lines to. ''' - policy_part_name = policy['name'] + '_Part' + policy_part_name = self._Escape(policy['name'] + '_Part') self._AddGuiString(policy_part_name, policy['label']) # Print the PART ... END PART section: @@ -117,6 +122,10 @@ class AdmWriter(template_writer.TemplateWriter): if policy['type'] == 'int': # The default max for NUMERIC values is 9999 which is too small for us. builder.AddLine('MIN 0 MAX 2000000000') + if policy['type'] in ('string', 'dict'): + # The default max for EDITTEXT values is 1023, which is too small for + # big JSON blobs and other string policies. + builder.AddLine('MAXLEN 1000000') if policy['type'] in ('int-enum', 'string-enum'): builder.AddLine('ITEMLIST', 1) for item in policy['items']: @@ -124,9 +133,9 @@ class AdmWriter(template_writer.TemplateWriter): value_text = 'NUMERIC ' + str(item['value']) else: value_text = '"' + item['value'] + '"' - builder.AddLine('NAME !!%s_DropDown VALUE %s' % - (item['name'], value_text)) - self._AddGuiString(item['name'] + '_DropDown', item['caption']) + string_id = self._Escape(item['name'] + '_DropDown') + builder.AddLine('NAME !!%s VALUE %s' % (string_id, value_text)) + self._AddGuiString(string_id, item['caption']) builder.AddLine('END ITEMLIST', -1) builder.AddLine('END PART', -1) @@ -135,10 +144,11 @@ class AdmWriter(template_writer.TemplateWriter): # This type can only be set through cloud policy. return - self._AddGuiString(policy['name'] + '_Policy', policy['caption']) - builder.AddLine('POLICY !!%s_Policy' % policy['name'], 1) + policy_name = self._Escape(policy['name'] + '_Policy') + self._AddGuiString(policy_name, policy['caption']) + builder.AddLine('POLICY !!%s' % policy_name, 1) self._WriteSupported(builder) - policy_explain_name = policy['name'] + '_Explain' + policy_explain_name = self._Escape(policy['name'] + '_Explain') self._AddGuiString(policy_explain_name, policy['desc']) builder.AddLine('EXPLAIN !!' + policy_explain_name) @@ -152,6 +162,9 @@ class AdmWriter(template_writer.TemplateWriter): builder.AddLine('END POLICY', -1) builder.AddLine() + def WriteComment(self, comment): + self.lines.AddLine('; ' + comment) + def WritePolicy(self, policy): if self.CanBeMandatory(policy): self._WritePolicy(policy, @@ -164,7 +177,7 @@ class AdmWriter(template_writer.TemplateWriter): self.recommended_policies) def BeginPolicyGroup(self, group): - category_name = group['name'] + '_Category' + category_name = self._Escape(group['name'] + '_Category') self._AddGuiString(category_name, group['caption']) self.policies.AddLine('CATEGORY !!' + category_name, 1) @@ -173,7 +186,7 @@ class AdmWriter(template_writer.TemplateWriter): self.policies.AddLine('') def BeginRecommendedPolicyGroup(self, group): - category_name = group['name'] + '_Category' + category_name = self._Escape(group['name'] + '_Category') self._AddGuiString(category_name, group['caption']) self.recommended_policies.AddLine('CATEGORY !!' + category_name, 1) @@ -205,6 +218,9 @@ class AdmWriter(template_writer.TemplateWriter): return lines def BeginTemplate(self): + if self._GetChromiumVersionString() is not None: + self.WriteComment(self.config['build'] + ' version: ' + \ + self._GetChromiumVersionString()) self._AddGuiString(self.config['win_supported_os'], self.messages['win_supported_winxpsp2']['text']) category_path = self.config['win_mandatory_category_path'] diff --git a/grit/format/policy_templates/writers/adm_writer_unittest.py b/grit/format/policy_templates/writers/adm_writer_unittest.py index 82374bb..c5c64f7 100644 --- a/grit/format/policy_templates/writers/adm_writer_unittest.py +++ b/grit/format/policy_templates/writers/adm_writer_unittest.py @@ -76,6 +76,42 @@ chromium="Chromium" chromium_recommended="Chromium - Recommended"''') self.CompareOutputs(output, expected_output) + def testVersionAnnotation(self): + # Test PListWriter in case of empty polices. + grd = self.PrepareTest(''' + { + 'policy_definitions': [], + 'placeholders': [], + 'messages': { + 'win_supported_winxpsp2': { + 'text': 'At least "Windows 3.11', 'desc': 'blah' + }, + 'doc_recommended': { + 'text': 'Recommended', 'desc': 'bleh' + } + } + }''') + output = self.GetOutput( + grd, 'fr', {'_chromium': '1', 'version':'39.0.0.0'}, 'adm', 'en') + expected_output = '; chromium version: 39.0.0.0\n' + \ + self.ConstructOutput(['MACHINE', 'USER'], ''' + CATEGORY !!chromium + KEYNAME "Software\\Policies\\Chromium" + + END CATEGORY + + CATEGORY !!chromium_recommended + KEYNAME "Software\\Policies\\Chromium\\Recommended" + + END CATEGORY + + +''', '''[Strings] +SUPPORTED_WINXPSP2="At least "Windows 3.11" +chromium="Chromium" +chromium_recommended="Chromium - Recommended"''') + self.CompareOutputs(output, expected_output) + def testMainPolicy(self): # Tests a policy group with a single policy of type 'main'. grd = self.PrepareTest(''' @@ -250,6 +286,7 @@ With a newline.""", PART !!StringPolicy_Part EDITTEXT VALUENAME "StringPolicy" + MAXLEN 1000000 END PART END POLICY @@ -266,6 +303,7 @@ With a newline.""", PART !!StringPolicy_Part EDITTEXT VALUENAME "StringPolicy" + MAXLEN 1000000 END PART END POLICY @@ -734,6 +772,7 @@ ListPolicy_Part="Label of list policy." PART !!DictionaryPolicy_Part EDITTEXT VALUENAME "DictionaryPolicy" + MAXLEN 1000000 END PART END POLICY @@ -750,6 +789,7 @@ ListPolicy_Part="Label of list policy." PART !!DictionaryPolicy_Part EDITTEXT VALUENAME "DictionaryPolicy" + MAXLEN 1000000 END PART END POLICY @@ -942,6 +982,7 @@ With a newline.""" PART !!Policy2_Part EDITTEXT VALUENAME "Policy2" + MAXLEN 1000000 END PART END POLICY @@ -984,5 +1025,103 @@ Policy2_Part="Caption of policy2." ''') self.CompareOutputs(output, expected_output) + def testDuplicatedStringEnumPolicy(self): + # Verifies that duplicated enum constants get merged, and that + # string constants get escaped. + grd = self.PrepareTest(''' + { + 'policy_definitions': [ + { + 'name': 'EnumPolicy.A', + 'type': 'string-enum', + 'caption': 'Caption of policy A.', + 'desc': 'Description of policy A.', + 'items': [ + {'name': 'tls1.2', 'value': 'tls1.2', 'caption': 'tls1.2' }, + ], + 'supported_on': ['chrome.win:39-'], + }, + { + 'name': 'EnumPolicy.B', + 'type': 'string-enum', + 'caption': 'Caption of policy B.', + 'desc': 'Description of policy B.', + 'items': [ + {'name': 'tls1.2', 'value': 'tls1.2', 'caption': 'tls1.2' }, + ], + 'supported_on': ['chrome.win:39-'], + }, + ], + 'placeholders': [], + 'messages': { + 'win_supported_winxpsp2': { + 'text': 'At least Windows 3.14', 'desc': 'blah' + }, + 'doc_recommended': { + 'text': 'Recommended', 'desc': 'bleh' + } + } + }''') + output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'adm', 'en') + expected_output = self.ConstructOutput( + ['MACHINE', 'USER'], ''' + CATEGORY !!google + CATEGORY !!googlechrome + KEYNAME "Software\\Policies\\Google\\Chrome" + + POLICY !!EnumPolicy_A_Policy + #if version >= 4 + SUPPORTED !!SUPPORTED_WINXPSP2 + #endif + EXPLAIN !!EnumPolicy_A_Explain + + PART !!EnumPolicy_A_Part DROPDOWNLIST + VALUENAME "EnumPolicy.A" + ITEMLIST + NAME !!tls1_2_DropDown VALUE "tls1.2" + END ITEMLIST + END PART + END POLICY + + POLICY !!EnumPolicy_B_Policy + #if version >= 4 + SUPPORTED !!SUPPORTED_WINXPSP2 + #endif + EXPLAIN !!EnumPolicy_B_Explain + + PART !!EnumPolicy_B_Part DROPDOWNLIST + VALUENAME "EnumPolicy.B" + ITEMLIST + NAME !!tls1_2_DropDown VALUE "tls1.2" + END ITEMLIST + END PART + END POLICY + + END CATEGORY + END CATEGORY + + CATEGORY !!google + CATEGORY !!googlechrome_recommended + KEYNAME "Software\\Policies\\Google\\Chrome\\Recommended" + + END CATEGORY + END CATEGORY + + +''', '''[Strings] +SUPPORTED_WINXPSP2="At least Windows 3.14" +google="Google" +googlechrome="Google Chrome" +googlechrome_recommended="Google Chrome - Recommended" +EnumPolicy_A_Policy="Caption of policy A." +EnumPolicy_A_Explain="Description of policy A." +EnumPolicy_A_Part="Caption of policy A." +tls1_2_DropDown="tls1.2" +EnumPolicy_B_Policy="Caption of policy B." +EnumPolicy_B_Explain="Description of policy B." +EnumPolicy_B_Part="Caption of policy B." +''') + self.CompareOutputs(output, expected_output) + if __name__ == '__main__': unittest.main() diff --git a/grit/format/policy_templates/writers/adml_writer.py b/grit/format/policy_templates/writers/adml_writer.py index c525602..64f8562 100644 --- a/grit/format/policy_templates/writers/adml_writer.py +++ b/grit/format/policy_templates/writers/adml_writer.py @@ -30,19 +30,24 @@ class ADMLWriter(xml_formatted_writer.XMLFormattedWriter): # describe the presentation of Policy-Groups and Policies. _presentation_table_elem = None - def _AddString(self, parent, id, text): - ''' Adds an ADML "string" element to the passed parent. The following + def _AddString(self, id, text): + ''' Adds an ADML "string" element to _string_table_elem. The following ADML snippet contains an example: <string id="$(id)">$(text)</string> Args: - parent: Parent element to which the new "string" element is added. id: ID of the newly created "string" element. text: Value of the newly created "string" element. ''' - string_elem = self.AddElement(parent, 'string', {'id': id}) - string_elem.appendChild(self._doc.createTextNode(text)) + id = id.replace('.', '_') + if id in self.strings_seen: + assert text == self.strings_seen[id] + else: + self.strings_seen[id] = text + string_elem = self.AddElement( + self._string_table_elem, 'string', {'id': id}) + string_elem.appendChild(self._doc.createTextNode(text)) def WritePolicy(self, policy): '''Generates the ADML elements for a Policy. @@ -75,9 +80,8 @@ class ADMLWriter(xml_formatted_writer.XMLFormattedWriter): else: policy_label = policy_name - self._AddString(self._string_table_elem, policy_name, policy_caption) - self._AddString(self._string_table_elem, policy_name + '_Explain', - policy_description) + self._AddString(policy_name, policy_caption) + self._AddString(policy_name + '_Explain', policy_description) presentation_elem = self.AddElement( self._presentation_table_elem, 'presentation', {'id': policy_name}) @@ -95,14 +99,12 @@ class ADMLWriter(xml_formatted_writer.XMLFormattedWriter): textbox_elem.appendChild(self._doc.createTextNode(policy_label + ':')) elif policy_type in ('int-enum', 'string-enum'): for item in policy['items']: - self._AddString(self._string_table_elem, item['name'], item['caption']) + self._AddString(item['name'], item['caption']) dropdownlist_elem = self.AddElement(presentation_elem, 'dropdownList', {'refId': policy_name}) dropdownlist_elem.appendChild(self._doc.createTextNode(policy_label)) elif policy_type in ('list', 'string-enum-list'): - self._AddString(self._string_table_elem, - policy_name + 'Desc', - policy_caption) + self._AddString(policy_name + 'Desc', policy_caption) listbox_elem = self.AddElement(presentation_elem, 'listBox', {'refId': policy_name + 'Desc'}) listbox_elem.appendChild(self._doc.createTextNode(policy_label)) @@ -128,39 +130,36 @@ class ADMLWriter(xml_formatted_writer.XMLFormattedWriter): ''' # Add ADML "string" elements to the string-table that are required by a # Policy-Group. - self._AddString(self._string_table_elem, group['name'] + '_group', - group['caption']) + self._AddString(group['name'] + '_group', group['caption']) - def _AddBaseStrings(self, string_table_elem, build): + def _AddBaseStrings(self, build): ''' Adds ADML "string" elements to the string-table that are referenced by the ADMX file but not related to any specific Policy-Group or Policy. ''' - self._AddString(string_table_elem, self.config['win_supported_os'], + self._AddString(self.config['win_supported_os'], self.messages['win_supported_winxpsp2']['text']) recommended_name = '%s - %s' % \ (self.config['app_name'], self.messages['doc_recommended']['text']) if build == 'chrome': - self._AddString(string_table_elem, - self.config['win_mandatory_category_path'][0], + self._AddString(self.config['win_mandatory_category_path'][0], 'Google') - self._AddString(string_table_elem, - self.config['win_mandatory_category_path'][1], + self._AddString(self.config['win_mandatory_category_path'][1], self.config['app_name']) - self._AddString(string_table_elem, - self.config['win_recommended_category_path'][1], + self._AddString(self.config['win_recommended_category_path'][1], recommended_name) elif build == 'chromium': - self._AddString(string_table_elem, - self.config['win_mandatory_category_path'][0], + self._AddString(self.config['win_mandatory_category_path'][0], self.config['app_name']) - self._AddString(string_table_elem, - self.config['win_recommended_category_path'][0], + self._AddString(self.config['win_recommended_category_path'][0], recommended_name) def BeginTemplate(self): dom_impl = minidom.getDOMImplementation('') self._doc = dom_impl.createDocument(None, 'policyDefinitionResources', None) + if self._GetChromiumVersionString() is not None: + self.AddComment(self._doc.documentElement, self.config['build'] + \ + ' version: ' + self._GetChromiumVersionString()) policy_definitions_resources_elem = self._doc.documentElement policy_definitions_resources_elem.attributes['revision'] = '1.0' policy_definitions_resources_elem.attributes['schemaVersion'] = '1.0' @@ -170,10 +169,14 @@ class ADMLWriter(xml_formatted_writer.XMLFormattedWriter): resources_elem = self.AddElement(policy_definitions_resources_elem, 'resources') self._string_table_elem = self.AddElement(resources_elem, 'stringTable') - self._AddBaseStrings(self._string_table_elem, self.config['build']) + self._AddBaseStrings(self.config['build']) self._presentation_table_elem = self.AddElement(resources_elem, 'presentationTable') + def Init(self): + # Map of all strings seen. + self.strings_seen = {} + def GetTemplateText(self): # Using "toprettyxml()" confuses the Windows Group Policy Editor # (gpedit.msc) because it interprets whitespace characters in text between diff --git a/grit/format/policy_templates/writers/adml_writer_unittest.py b/grit/format/policy_templates/writers/adml_writer_unittest.py index 8a8f4f7..08bec58 100644 --- a/grit/format/policy_templates/writers/adml_writer_unittest.py +++ b/grit/format/policy_templates/writers/adml_writer_unittest.py @@ -77,6 +77,20 @@ class AdmlWriterUnittest(xml_writer_base_unittest.XmlWriterBaseTest): '</resources></policyDefinitionResources>') self.AssertXMLEquals(output, expected_output) + def testVersionAnnotation(self): + self.writer.config['version'] = '39.0.0.0' + self.writer.BeginTemplate() + self.writer.EndTemplate() + output = self.writer.GetTemplateText() + expected_output = ( + '<?xml version="1.0" ?><policyDefinitionResources' + ' revision="1.0" schemaVersion="1.0"><!--test version: 39.0.0.0-->' + '<displayName/><description/><resources><stringTable>' + '<string id="SUPPORTED_TESTOS">Supported on' + ' Test OS or higher</string></stringTable><presentationTable/>' + '</resources></policyDefinitionResources>') + self.AssertXMLEquals(output, expected_output) + def testPolicyGroup(self): empty_policy_group = { 'name': 'PolicyGroup', @@ -362,6 +376,62 @@ class AdmlWriterUnittest(xml_writer_base_unittest.XmlWriterBaseTest): ] })) + def testStringEncodings(self): + enum_policy_a = { + 'name': 'EnumPolicy.A', + 'type': 'string-enum', + 'caption': 'Enum policy A caption', + 'label': 'Enum policy A label', + 'desc': 'This is a test description.', + 'items': [ + { + 'name': 'tls1.2', + 'value': 'tls1.2', + 'caption': 'tls1.2', + } + ], + } + enum_policy_b = { + 'name': 'EnumPolicy.B', + 'type': 'string-enum', + 'caption': 'Enum policy B caption', + 'label': 'Enum policy B label', + 'desc': 'This is a test description.', + 'items': [ + { + 'name': 'tls1.2', + 'value': 'tls1.2', + 'caption': 'tls1.2', + } + ], + } + self. _InitWriterForAddingPolicies(self.writer, enum_policy_a) + self.writer.WritePolicy(enum_policy_a) + self.writer.WritePolicy(enum_policy_b) + # Assert generated string elements. + output = self.GetXMLOfChildren(self.writer._string_table_elem) + expected_output = ( + '<string id="EnumPolicy_A">Enum policy A caption</string>\n' + '<string id="EnumPolicy_A_Explain">' + 'This is a test description.</string>\n' + '<string id="tls1_2">tls1.2</string>\n' + '<string id="EnumPolicy_B">Enum policy B caption</string>\n' + '<string id="EnumPolicy_B_Explain">' + 'This is a test description.</string>\n') + self.AssertXMLEquals(output, expected_output) + # Assert generated presentation elements. + output = self.GetXMLOfChildren(self.writer._presentation_table_elem) + expected_output = ( + '<presentation id="EnumPolicy.A">\n' + ' <dropdownList refId="EnumPolicy.A">' + 'Enum policy A label</dropdownList>\n' + '</presentation>\n' + '<presentation id="EnumPolicy.B">\n' + ' <dropdownList refId="EnumPolicy.B">' + 'Enum policy B label</dropdownList>\n' + '</presentation>') + self.AssertXMLEquals(output, expected_output) + if __name__ == '__main__': unittest.main() diff --git a/grit/format/policy_templates/writers/admx_writer.py b/grit/format/policy_templates/writers/admx_writer.py index 0d4394b..d657834 100644 --- a/grit/format/policy_templates/writers/admx_writer.py +++ b/grit/format/policy_templates/writers/admx_writer.py @@ -32,6 +32,7 @@ class ADMXWriter(xml_formatted_writer.XMLFormattedWriter): Args: name: Name of the referenced ADML string. ''' + name = name.replace('.', '_') return '$(string.' + name + ')' def _AdmlStringExplain(self, name): @@ -39,6 +40,7 @@ class ADMXWriter(xml_formatted_writer.XMLFormattedWriter): Args: name: Name of the referenced ADML explanation. ''' + name = name.replace('.', '_') return '$(string.' + name + '_Explain)' def _AdmlPresentation(self, name): @@ -166,6 +168,7 @@ class ADMXWriter(xml_formatted_writer.XMLFormattedWriter): attributes = { 'id': name, 'valueName': name, + 'maxLength': '1000000', } self.AddElement(parent, 'text', attributes) @@ -349,6 +352,9 @@ class ADMXWriter(xml_formatted_writer.XMLFormattedWriter): ''' dom_impl = minidom.getDOMImplementation('') self._doc = dom_impl.createDocument(None, 'policyDefinitions', None) + if self._GetChromiumVersionString() is not None: + self.AddComment(self._doc.documentElement, self.config['build'] + \ + ' version: ' + self._GetChromiumVersionString()) policy_definitions_elem = self._doc.documentElement policy_definitions_elem.attributes['revision'] = '1.0' diff --git a/grit/format/policy_templates/writers/admx_writer_unittest.py b/grit/format/policy_templates/writers/admx_writer_unittest.py index cb3d39e..8bdb7a4 100644 --- a/grit/format/policy_templates/writers/admx_writer_unittest.py +++ b/grit/format/policy_templates/writers/admx_writer_unittest.py @@ -37,7 +37,8 @@ class AdmxWriterUnittest(xml_writer_base_unittest.XmlWriterBaseTest): 'win_mandatory_category_path': ['test_category'], 'win_recommended_category_path': ['test_recommended_category'], 'admx_namespace': 'ADMXWriter.Test.Namespace', - 'admx_prefix': 'test_prefix' + 'admx_prefix': 'test_prefix', + 'build': 'test_product', } self.writer = admx_writer.GetWriter(config) self.writer.Init() @@ -82,6 +83,38 @@ class AdmxWriterUnittest(xml_writer_base_unittest.XmlWriterBaseTest): '</policyDefinitions>') self.AssertXMLEquals(output, expected_output) + def testEmptyVersion(self): + self.writer.config['version'] = '39.0.0.0' + self.writer.BeginTemplate() + self.writer.EndTemplate() + + output = self.writer.GetTemplateText() + expected_output = ( + '<?xml version="1.0" ?>\n' + '<policyDefinitions revision="1.0" schemaVersion="1.0">\n' + ' <!--test_product version: 39.0.0.0-->\n' + ' <policyNamespaces>\n' + ' <target namespace="ADMXWriter.Test.Namespace"' + ' prefix="test_prefix"/>\n' + ' <using namespace="Microsoft.Policies.Windows" prefix="windows"/>\n' + ' </policyNamespaces>\n' + ' <resources minRequiredRevision="1.0"/>\n' + ' <supportedOn>\n' + ' <definitions>\n' + ' <definition displayName="' + '$(string.SUPPORTED_TESTOS)" name="SUPPORTED_TESTOS"/>\n' + ' </definitions>\n' + ' </supportedOn>\n' + ' <categories>\n' + ' <category displayName="$(string.test_category)"' + ' name="test_category"/>\n' + ' <category displayName="$(string.test_recommended_category)"' + ' name="test_recommended_category"/>\n' + ' </categories>\n' + ' <policies/>\n' + '</policyDefinitions>') + self.AssertXMLEquals(output, expected_output) + def testEmptyPolicyGroup(self): empty_policy_group = { 'name': 'PolicyGroup', @@ -276,7 +309,8 @@ class AdmxWriterUnittest(xml_writer_base_unittest.XmlWriterBaseTest): ' <parentCategory ref="PolicyGroup"/>\n' ' <supportedOn ref="SUPPORTED_TESTOS"/>\n' ' <elements>\n' - ' <text id="SampleStringPolicy" valueName="SampleStringPolicy"/>\n' + ' <text id="SampleStringPolicy" maxLength="1000000"' + ' valueName="SampleStringPolicy"/>\n' ' </elements>\n' '</policy>') self.AssertXMLEquals(output, expected_output) @@ -454,8 +488,8 @@ class AdmxWriterUnittest(xml_writer_base_unittest.XmlWriterBaseTest): ' <parentCategory ref="PolicyGroup"/>\n' ' <supportedOn ref="SUPPORTED_TESTOS"/>\n' ' <elements>\n' - ' <text id="SampleDictionaryPolicy" ' - 'valueName="SampleDictionaryPolicy"/>\n' + ' <text id="SampleDictionaryPolicy" maxLength="1000000"' + ' valueName="SampleDictionaryPolicy"/>\n' ' </elements>\n' '</policy>') self.AssertXMLEquals(output, expected_output) @@ -473,6 +507,67 @@ class AdmxWriterUnittest(xml_writer_base_unittest.XmlWriterBaseTest): ] })) + def testStringEncodings(self): + enum_policy_a = { + 'name': 'SampleEnumPolicy.A', + 'type': 'string-enum', + 'items': [ + {'name': 'tls1.2', 'value': 'tls1.2'} + ] + } + enum_policy_b = { + 'name': 'SampleEnumPolicy.B', + 'type': 'string-enum', + 'items': [ + {'name': 'tls1.2', 'value': 'tls1.2'} + ] + } + + dom_impl = minidom.getDOMImplementation('') + self.writer._doc = dom_impl.createDocument(None, 'policyDefinitions', None) + self.writer._active_policies_elem = self.writer._doc.documentElement + self.writer._active_mandatory_policy_group_name = 'PolicyGroup' + self.writer.WritePolicy(enum_policy_a) + self.writer.WritePolicy(enum_policy_b) + output = self.writer.GetTemplateText() + expected_output = ( + '<?xml version="1.0" ?>\n' + '<policyDefinitions>\n' + ' <policy class="TestClass" displayName="$(string.SampleEnumPolicy_A)"' + ' explainText="$(string.SampleEnumPolicy_A_Explain)"' + ' key="Software\\Policies\\Test" name="SampleEnumPolicy.A"' + ' presentation="$(presentation.SampleEnumPolicy.A)">\n' + ' <parentCategory ref="PolicyGroup"/>\n' + ' <supportedOn ref="SUPPORTED_TESTOS"/>\n' + ' <elements>\n' + ' <enum id="SampleEnumPolicy.A" valueName="SampleEnumPolicy.A">\n' + ' <item displayName="$(string.tls1_2)">\n' + ' <value>\n' + ' <string>tls1.2</string>\n' + ' </value>\n' + ' </item>\n' + ' </enum>\n' + ' </elements>\n' + ' </policy>\n' + ' <policy class="TestClass" displayName="$(string.SampleEnumPolicy_B)"' + ' explainText="$(string.SampleEnumPolicy_B_Explain)"' + ' key="Software\\Policies\\Test" name="SampleEnumPolicy.B"' + ' presentation="$(presentation.SampleEnumPolicy.B)">\n' + ' <parentCategory ref="PolicyGroup"/>\n' + ' <supportedOn ref="SUPPORTED_TESTOS"/>\n' + ' <elements>\n' + ' <enum id="SampleEnumPolicy.B" valueName="SampleEnumPolicy.B">\n' + ' <item displayName="$(string.tls1_2)">\n' + ' <value>\n' + ' <string>tls1.2</string>\n' + ' </value>\n' + ' </item>\n' + ' </enum>\n' + ' </elements>\n' + ' </policy>\n' + '</policyDefinitions>') + self.AssertXMLEquals(output, expected_output) + if __name__ == '__main__': unittest.main() diff --git a/grit/format/policy_templates/writers/doc_writer.py b/grit/format/policy_templates/writers/doc_writer.py index d8f108d..e90e16c 100644 --- a/grit/format/policy_templates/writers/doc_writer.py +++ b/grit/format/policy_templates/writers/doc_writer.py @@ -590,6 +590,10 @@ class DocWriter(xml_formatted_writer.XMLFormattedWriter): def BeginTemplate(self): # Add a <div> for the summary section. + if self._GetChromiumVersionString() is not None: + self.AddComment(self._main_div, self.config['build'] + \ + ' version: ' + self._GetChromiumVersionString()) + summary_div = self.AddElement(self._main_div, 'div') self.AddElement(summary_div, 'a', {'name': 'top'}) self.AddElement(summary_div, 'br') diff --git a/grit/format/policy_templates/writers/doc_writer_unittest.py b/grit/format/policy_templates/writers/doc_writer_unittest.py index 15d8b85..db03808 100644 --- a/grit/format/policy_templates/writers/doc_writer_unittest.py +++ b/grit/format/policy_templates/writers/doc_writer_unittest.py @@ -39,6 +39,7 @@ class DocWriterUnittest(writer_unittest_common.WriterUnittestCommon): 'os_name': 'Chrome OS', 'win_reg_mandatory_key_name': 'MockKey', 'win_reg_recommended_key_name': 'MockKeyRec', + 'build': 'test_product', }) self.writer.messages = { 'doc_back_to_top': {'text': '_test_back_to_top'}, @@ -103,6 +104,31 @@ class DocWriterUnittest(writer_unittest_common.WriterUnittestCommon): '<div/>' '</div>') + def testVersionAnnotation(self): + # Test if DocWriter creates the skeleton of the document correctly. + self.writer.config['version'] = '39.0.0.0' + self.writer.BeginTemplate() + self.assertEquals( + self.writer._main_div.toxml(), + '<div>' + '<!--test_product version: 39.0.0.0-->' + '<div>' + '<a name="top"/><br/>_test_intro<br/><br/><br/>' + '<table style="style_table;">' + '<thead><tr style="style_tr;">' + '<td style="style_td;style_td.left;style_thead td;">' + '_test_name_column_title' + '</td>' + '<td style="style_td;style_td.right;style_thead td;">' + '_test_description_column_title' + '</td>' + '</tr></thead>' + '<tbody/>' + '</table>' + '</div>' + '<div/>' + '</div>') + def testGetLocalizedMessage(self): # Test if localized messages are retrieved correctly. self.writer.messages = { diff --git a/grit/format/policy_templates/writers/ios_plist_writer.py b/grit/format/policy_templates/writers/ios_plist_writer.py index 1da64aa..b726ffa 100644 --- a/grit/format/policy_templates/writers/ios_plist_writer.py +++ b/grit/format/policy_templates/writers/ios_plist_writer.py @@ -97,6 +97,9 @@ class IOSPlistWriter(plist_writer.PListWriter): self._plist.attributes['version'] = '1.0' self._root_dict = self.AddElement(self._plist, 'dict') self.AddComment(self._root_dict, CHROME_POLICY_COMMENT) + if self._GetChromiumVersionString() is not None: + self.AddComment(self._root_dict, ' ' + self.config['build'] + \ + ' version: ' + self._GetChromiumVersionString() + ' ') self._dict = self._AddKeyValuePair(self._root_dict, 'ChromePolicy', 'dict') self._encoded_plist.attributes['version'] = '1.0' diff --git a/grit/format/policy_templates/writers/ios_plist_writer_unittest.py b/grit/format/policy_templates/writers/ios_plist_writer_unittest.py index 4743e4e..0fdecb1 100644 --- a/grit/format/policy_templates/writers/ios_plist_writer_unittest.py +++ b/grit/format/policy_templates/writers/ios_plist_writer_unittest.py @@ -55,11 +55,17 @@ class IOSPListWriterUnittest(writer_unittest_common.WriterUnittestCommon): expected_output, parse, decode_and_parse): + + + _defines = { '_chromium': '1', + 'mac_bundle_id': 'com.example.Test', + 'version': '39.0.0.0' } + # Generate the grit output for |templates|. output = self.GetOutput( self.PrepareTest(templates), 'fr', - { '_chromium': '1', 'mac_bundle_id': 'com.example.Test' }, + _defines, 'ios_plist', 'en') @@ -124,6 +130,17 @@ class IOSPListWriterUnittest(writer_unittest_common.WriterUnittestCommon): expected = {} self._VerifyGeneratedOutput(templates, expected) + def testEmptyVersion(self): + templates = ''' + { + 'policy_definitions': [], + 'placeholders': [], + 'messages': {}, + } + ''' + expected = {} + self._VerifyGeneratedOutput(templates, expected) + def testBoolean(self): templates = self._MakeTemplate('BooleanPolicy', 'main', 'True') expected = { diff --git a/grit/format/policy_templates/writers/json_writer.py b/grit/format/policy_templates/writers/json_writer.py index f5af8c1..4dfd282 100644 --- a/grit/format/policy_templates/writers/json_writer.py +++ b/grit/format/policy_templates/writers/json_writer.py @@ -39,6 +39,9 @@ class JsonWriter(template_writer.TemplateWriter): def PreprocessPolicies(self, policy_list): return self.FlattenGroupsAndSortPolicies(policy_list) + def WriteComment(self, comment): + self._out.append('// ' + comment) + def WritePolicy(self, policy): if policy['type'] == 'external': # This type can only be set through cloud policy. @@ -69,6 +72,9 @@ class JsonWriter(template_writer.TemplateWriter): self._first_written = False def BeginTemplate(self): + if self._GetChromiumVersionString() is not None: + self.WriteComment(self.config['build'] + ''' version: ''' + \ + self._GetChromiumVersionString()) self._out.append(TEMPLATE_HEADER) def EndTemplate(self): diff --git a/grit/format/policy_templates/writers/json_writer_unittest.py b/grit/format/policy_templates/writers/json_writer_unittest.py index b2ed1ef..8f3c745 100644 --- a/grit/format/policy_templates/writers/json_writer_unittest.py +++ b/grit/format/policy_templates/writers/json_writer_unittest.py @@ -24,6 +24,15 @@ TEMPLATE_HEADER="""\ { """ +TEMPLATE_HEADER_WITH_VERSION="""\ +// chromium version: 39.0.0.0 +// Policy template for Linux. +// Uncomment the policies you wish to activate and change their values to +// something useful for your case. The provided values are for reference only +// and do not provide meaningful defaults! +{ +""" + HEADER_DELIMETER="""\ //------------------------------------------------------------------------- @@ -55,10 +64,23 @@ class JsonWriterUnittest(writer_unittest_common.WriterUnittestCommon): ' "placeholders": [],' ' "messages": {},' '}') - output = self.GetOutput(grd, 'fr', {'_chromium': '1',}, 'json', 'en') + output = self.GetOutput(grd, 'fr', {'_chromium': '1'}, 'json', 'en') expected_output = TEMPLATE_HEADER + '}' self.CompareOutputs(output, expected_output) + def testEmptyWithVersion(self): + # Test the handling of an empty policy list. + grd = self.PrepareTest( + '{' + ' "policy_definitions": [],' + ' "placeholders": [],' + ' "messages": {},' + '}') + output = self.GetOutput( + grd, 'fr', {'_chromium': '1', 'version':'39.0.0.0'}, 'json', 'en') + expected_output = TEMPLATE_HEADER_WITH_VERSION + '}' + self.CompareOutputs(output, expected_output) + def testMainPolicy(self): # Tests a policy group with a single policy of type 'main'. grd = self.PrepareTest( diff --git a/grit/format/policy_templates/writers/plist_strings_writer.py b/grit/format/policy_templates/writers/plist_strings_writer.py index 966aaf2..4257bf8 100644 --- a/grit/format/policy_templates/writers/plist_strings_writer.py +++ b/grit/format/policy_templates/writers/plist_strings_writer.py @@ -22,6 +22,9 @@ class PListStringsWriter(template_writer.TemplateWriter): [lang].lproj subdirectories of the manifest bundle. ''' + def WriteComment(self, comment): + self._out.append('/* ' + comment + ' */' ) + def _AddToStringTable(self, item_name, caption, desc): '''Add a title and a description of an item to the string table. @@ -63,6 +66,9 @@ class PListStringsWriter(template_writer.TemplateWriter): def BeginTemplate(self): app_name = plist_helper.GetPlistFriendlyName(self.config['app_name']) + if self._GetChromiumVersionString() is not None: + self.WriteComment(self.config['build'] + ''' version: ''' + \ + self._GetChromiumVersionString()) self._AddToStringTable( app_name, self.config['app_name'], diff --git a/grit/format/policy_templates/writers/plist_strings_writer_unittest.py b/grit/format/policy_templates/writers/plist_strings_writer_unittest.py index 17fc85c..efad6f2 100644 --- a/grit/format/policy_templates/writers/plist_strings_writer_unittest.py +++ b/grit/format/policy_templates/writers/plist_strings_writer_unittest.py @@ -43,6 +43,33 @@ class PListStringsWriterUnittest(writer_unittest_common.WriterUnittestCommon): 'Chromium.pfm_description = "Chromium preferen\\"ces";') self.assertEquals(output.strip(), expected_output.strip()) + def testEmptyVersion(self): + # Test PListStringsWriter in case of empty polices. + grd = self.PrepareTest(''' + { + 'policy_definitions': [], + 'placeholders': [], + 'messages': { + 'mac_chrome_preferences': { + 'text': '$1 preferen"ces', + 'desc': 'blah' + } + } + }''') + output = self.GetOutput( + grd, + 'fr', + {'_chromium': '1', + 'mac_bundle_id': 'com.example.Test', + 'version': '39.0.0.0'}, + 'plist_strings', + 'en') + expected_output = ( + '/* chromium version: 39.0.0.0 */\n' + 'Chromium.pfm_title = "Chromium";\n' + 'Chromium.pfm_description = "Chromium preferen\\"ces";') + self.assertEquals(output.strip(), expected_output.strip()) + def testMainPolicy(self): # Tests a policy group with a single policy of type 'main'. grd = self.PrepareTest(''' diff --git a/grit/format/policy_templates/writers/plist_writer.py b/grit/format/policy_templates/writers/plist_writer.py index 6d929d6..cae6844 100644 --- a/grit/format/policy_templates/writers/plist_writer.py +++ b/grit/format/policy_templates/writers/plist_writer.py @@ -120,7 +120,9 @@ class PListWriter(xml_formatted_writer.XMLFormattedWriter): def BeginTemplate(self): self._plist.attributes['version'] = '1' dict = self.AddElement(self._plist, 'dict') - + if self._GetChromiumVersionString() is not None: + self.AddComment(self._plist, self.config['build'] + ' version: ' + \ + self._GetChromiumVersionString()) app_name = plist_helper.GetPlistFriendlyName(self.config['app_name']) self._AddStringKeyValuePair(dict, 'pfm_name', app_name) self._AddStringKeyValuePair(dict, 'pfm_description', '') diff --git a/grit/format/policy_templates/writers/plist_writer_unittest.py b/grit/format/policy_templates/writers/plist_writer_unittest.py index ddbdbfe..6186c15 100644 --- a/grit/format/policy_templates/writers/plist_writer_unittest.py +++ b/grit/format/policy_templates/writers/plist_writer_unittest.py @@ -52,6 +52,41 @@ class PListWriterUnittest(writer_unittest_common.WriterUnittestCommon): </dict> </plist>''' % (product_name, bundle_id, policies) + def _GetExpectedOutputsWithVersion(self, product_name, bundle_id, policies, + version): + '''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> + <!--%s--> +</plist>''' % (product_name, bundle_id, policies, version) + def testEmpty(self): # Test PListWriter in case of empty polices. grd = self.PrepareTest(''' @@ -71,6 +106,30 @@ class PListWriterUnittest(writer_unittest_common.WriterUnittestCommon): 'Chromium', 'com.example.Test', '<array/>') self.assertEquals(output.strip(), expected_output.strip()) + def testEmptyVersion(self): + # Test PListWriter in case of empty polices. + grd = self.PrepareTest(''' + { + 'policy_definitions': [], + 'placeholders': [], + 'messages': {}, + }''') + + output = self.GetOutput( + grd, + 'fr', + {'_chromium': '1', + 'mac_bundle_id': 'com.example.Test', + 'version': '39.0.0.0'}, + 'plist', + 'en') + expected_output = self._GetExpectedOutputsWithVersion( + 'Chromium', + 'com.example.Test', + '<array/>', + 'chromium version: 39.0.0.0') + self.assertEquals(output.strip(), expected_output.strip()) + def testMainPolicy(self): # Tests a policy group with a single policy of type 'main'. grd = self.PrepareTest(''' diff --git a/grit/format/policy_templates/writers/reg_writer.py b/grit/format/policy_templates/writers/reg_writer.py index ad83046..70c87a3 100644 --- a/grit/format/policy_templates/writers/reg_writer.py +++ b/grit/format/policy_templates/writers/reg_writer.py @@ -82,6 +82,9 @@ class RegWriter(template_writer.TemplateWriter): list.append('"%s"=%s' % (policy['name'], example_value_str)) + def WriteComment(self, comment): + self._prefix.append('; ' + comment) + def WritePolicy(self, policy): if self.CanBeMandatory(policy): self._WritePolicy(policy, @@ -103,8 +106,12 @@ class RegWriter(template_writer.TemplateWriter): self._mandatory = [] self._recommended = [] self._last_key = {} + self._prefix = [] def GetTemplateText(self): - prefix = ['Windows Registry Editor Version 5.00'] - all = prefix + self._mandatory + self._recommended + self._prefix.append('Windows Registry Editor Version 5.00') + if self._GetChromiumVersionString() is not None: + self.WriteComment(self.config['build'] + ' version: ' + \ + self._GetChromiumVersionString()) + all = self._prefix + self._mandatory + self._recommended return self.NEWLINE.join(all) diff --git a/grit/format/policy_templates/writers/reg_writer_unittest.py b/grit/format/policy_templates/writers/reg_writer_unittest.py index 88fb2e2..2851a8b 100644 --- a/grit/format/policy_templates/writers/reg_writer_unittest.py +++ b/grit/format/policy_templates/writers/reg_writer_unittest.py @@ -48,6 +48,20 @@ class RegWriterUnittest(writer_unittest_common.WriterUnittestCommon): expected_output = 'Windows Registry Editor Version 5.00' self.CompareOutputs(output, expected_output) + def testEmptyVersion(self): + # Test the handling of an empty policy list. + grd = self.PrepareTest( + '{' + ' "policy_definitions": [],' + ' "placeholders": [],' + ' "messages": {}' + '}') + output = self.GetOutput( + grd, 'fr', {'_chromium': '1', 'version': '39.0.0.0' }, 'reg', 'en') + expected_output = ('Windows Registry Editor Version 5.00\r\n' + '; chromium version: 39.0.0.0\r\n') + self.CompareOutputs(output, expected_output) + def testMainPolicy(self): # Tests a policy group with a single policy of type 'main'. grd = self.PrepareTest( diff --git a/grit/format/policy_templates/writers/template_writer.py b/grit/format/policy_templates/writers/template_writer.py index bd48425..d489d64 100644 --- a/grit/format/policy_templates/writers/template_writer.py +++ b/grit/format/policy_templates/writers/template_writer.py @@ -102,6 +102,15 @@ class TemplateWriter(object): is_supported = lambda x: platform in x['platforms'] return any(filter(is_supported, policy['supported_on'])) + def _GetChromiumVersionString(self): + '''Returns the Chromium version string stored in the environment variable + version (if it is set). + + Returns: The Chromium version string or None if it has not been set.''' + + if 'version' in self.config: + return self.config['version'] + def _GetPoliciesForWriter(self, group): '''Filters the list of policies in the passed group that are supported by the writer. @@ -191,6 +200,13 @@ class TemplateWriter(object): ''' raise NotImplementedError() + def WriteComment(self, comment): + '''Appends the comment to the internal buffer. + + comment: The comment to be added. + ''' + raise NotImplementedError() + def WriteRecommendedPolicy(self, policy): '''Appends the template text corresponding to a recommended policy into the internal buffer. diff --git a/grit/format/policy_templates/writers/xml_formatted_writer.py b/grit/format/policy_templates/writers/xml_formatted_writer.py index dad3717..5917fb4 100644 --- a/grit/format/policy_templates/writers/xml_formatted_writer.py +++ b/grit/format/policy_templates/writers/xml_formatted_writer.py @@ -31,7 +31,7 @@ class XMLFormattedWriter(template_writer.TemplateWriter): doc = parent.ownerDocument element = doc.createElement(name) - for key, value in attrs.iteritems(): + for key, value in sorted(attrs.iteritems()): element.setAttribute(key, value) if text: element.appendChild(doc.createTextNode(text)) diff --git a/grit/node/misc.py b/grit/node/misc.py index 9a23263..64c4690 100755 --- a/grit/node/misc.py +++ b/grit/node/misc.py @@ -292,6 +292,11 @@ class GritNode(base.Node): """ return self.attrs['base_dir'] + def SetShouldOutputAllResourceDefines(self, value): + """Overrides the value of output_all_resource_defines found in the grd file. + """ + self.attrs['output_all_resource_defines'] = 'true' if value else 'false' + def ShouldOutputAllResourceDefines(self): """Returns true if all resource defines should be output, false if defines for resources not emitted to resource files should be diff --git a/grit/testdata/whitelist.txt b/grit/testdata/whitelist.txt new file mode 100644 index 0000000..5b3aca4 --- /dev/null +++ b/grit/testdata/whitelist.txt @@ -0,0 +1,4 @@ +IDS_MESSAGE_WHITELISTED +IDR_STRUCTURE_WHITELISTED +IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED +IDR_INCLUDE_WHITELISTED diff --git a/grit/testdata/whitelist_resources.grd b/grit/testdata/whitelist_resources.grd new file mode 100644 index 0000000..9925688 --- /dev/null +++ b/grit/testdata/whitelist_resources.grd @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" + current_release="1" + output_all_resource_defines="false"> + <outputs> + <output filename="whitelist_test_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="whitelist_test_resources_map.cc" + type="resource_file_map_source" /> + <output filename="whitelist_test_resources_map.h" + type="resource_map_header" /> + <output filename="whitelist_test_resources.pak" type="data_package" /> + </outputs> + <translations> + <file path="substitute.xmb" lang="sv" /> + </translations> + <release seq="1"> + <structures> + <structure name="IDR_STRUCTURE_WHITELISTED" file="browser.html" + type="chrome_html" > + </structure> + <structure name="IDR_STRUCTURE_NOT_WHITELISTED" file="deleted.html" + type="chrome_html" > + </structure> + <if expr="True"> + <structure name="IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED" + file="details.html" + type="chrome_html" > + </structure> + <structure name="IDR_STRUCTURE_IN_TRUE_IF_NOT_WHITELISTED" + file="error.html" + type="chrome_html" > + </structure> + </if> + <if expr="False"> + <structure name="IDR_STRUCTURE_IN_FALSE_IF_WHITELISTED" + file="status.html" + type="chrome_html" > + </structure> + <structure name="IDR_STRUCTURE_IN_FALSE_IF_NOT_WHITELISTED" + file="simple.html" + type="chrome_html" > + </structure> + </if> + </structures> + <includes> + <include name="IDR_INCLUDE_WHITELISTED" file="klonk.ico" + type="BINDATA" /> + <include name="IDR_INCLUDE_NOT_WHITELISTED" file="klonk.rc" + type="BINDATA" /> + </includes> + </release> +</grit> diff --git a/grit/testdata/whitelist_strings.grd b/grit/testdata/whitelist_strings.grd new file mode 100644 index 0000000..df80f5f --- /dev/null +++ b/grit/testdata/whitelist_strings.grd @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" + current_release="1" + output_all_resource_defines="false"> + <outputs > + <output filename="whitelist_test_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="en_whitelist_test_strings.rc" type="rc_all" lang="en" /> + </outputs> + <release seq="1"> + <messages> + <message name="IDS_MESSAGE_WHITELISTED" + desc="A message in the whiltelist file."> + Whitelisted. + </message> + <message name="IDS_MESSAGE_NOT_WHITELISTED" + desc="A message that isn't in the whiltelist file."> + Not whitelisted. + </message> + </messages> + </release> +</grit> diff --git a/grit/tool/build.py b/grit/tool/build.py index 537e2c6..c3c1aff 100644 --- a/grit/tool/build.py +++ b/grit/tool/build.py @@ -104,6 +104,11 @@ Options: and {numeric_id}. E.g. "#define {textual_id} {numeric_id}" Otherwise it will use the default "#define SYMBOL 1234" + --output-all-resource-defines + --no-output-all-resource-defines If specified, overrides the value of the + output_all_resource_defines attribute of the root <grit> + element of the input .grd file. + Conditional inclusion of resources only affects the output of files which control which resources get linked into a binary, e.g. it affects .rc files meant for compilation but it does not affect resource header files (that define @@ -123,8 +128,11 @@ are exported to translation interchange files (e.g. XMB files), etc. depfile = None depdir = None rc_header_format = None + output_all_resource_defines = None (own_opts, args) = getopt.getopt(args, 'a:o:D:E:f:w:t:h:', - ('depdir=','depfile=','assert-file-list=')) + ('depdir=','depfile=','assert-file-list=', + 'output-all-resource-defines', + 'no-output-all-resource-defines',)) for (key, val) in own_opts: if key == '-a': assert_output_files.append(val) @@ -146,6 +154,10 @@ are exported to translation interchange files (e.g. XMB files), etc. first_ids_file = val elif key == '-w': whitelist_filenames.append(val) + elif key == '--output-all-resource-defines': + output_all_resource_defines = True + elif key == '--no-output-all-resource-defines': + output_all_resource_defines = False elif key == '-t': target_platform = val elif key == '-h': @@ -178,6 +190,12 @@ are exported to translation interchange files (e.g. XMB files), etc. first_ids_file=first_ids_file, defines=self.defines, target_platform=target_platform) + + # If the output_all_resource_defines option is specified, override the value + # found in the grd file. + if output_all_resource_defines is not None: + self.res.SetShouldOutputAllResourceDefines(output_all_resource_defines) + # Set an output context so that conditionals can use defines during the # gathering stage; we use a dummy language here since we are not outputting # a specific language. @@ -224,11 +242,13 @@ are exported to translation interchange files (e.g. XMB files), etc. # be written into the target files (skip markers). from grit.node import include from grit.node import message + from grit.node import structure for node in start_node: # Same trick data_pack.py uses to see what nodes actually result in # real items. if (isinstance(node, include.IncludeNode) or - isinstance(node, message.MessageNode)): + isinstance(node, message.MessageNode) or + isinstance(node, structure.StructureNode)): text_ids = node.GetTextualIds() # Mark the item to be skipped if it wasn't in the whitelist. if text_ids and text_ids[0] not in whitelist_names: @@ -363,12 +383,21 @@ are exported to translation interchange files (e.g. XMB files), etc. for i in self.res.GetOutputFiles()]) if asserted != actual: - print '''Asserted file list does not match. - -Expected output files: %s - -Actual output files: %s -''' % (asserted, actual) + missing = list(set(actual) - set(asserted)) + extra = list(set(asserted) - set(actual)) + error = '''Asserted file list does not match. + +Expected output files: +%s +Actual output files: +%s +Missing output files: +%s +Extra output files: +%s +''' + print error % ('\n'.join(asserted), '\n'.join(actual), '\n'.join(missing), + '\n'.join(extra)) return False return True diff --git a/grit/tool/build_unittest.py b/grit/tool/build_unittest.py index debe4d4..b687bb3 100644 --- a/grit/tool/build_unittest.py +++ b/grit/tool/build_unittest.py @@ -6,6 +6,7 @@ '''Unit tests for the 'grit build' tool. ''' +import codecs import os import sys import tempfile @@ -85,5 +86,165 @@ class BuildUnittest(unittest.TestCase): '-a', os.path.abspath( os.path.join(output_dir, 'resource.h'))])) + def _verifyWhitelistedOutput(self, + filename, + whitelisted_ids, + non_whitelisted_ids, + encoding='utf8'): + self.failUnless(os.path.exists(filename)) + whitelisted_ids_found = [] + non_whitelisted_ids_found = [] + with codecs.open(filename, encoding=encoding) as f: + for line in f.readlines(): + for whitelisted_id in whitelisted_ids: + if whitelisted_id in line: + whitelisted_ids_found.append(whitelisted_id) + for non_whitelisted_id in non_whitelisted_ids: + if non_whitelisted_id in line: + non_whitelisted_ids_found.append(non_whitelisted_id) + self.longMessage = True + self.assertEqual(whitelisted_ids, + whitelisted_ids_found, + '\nin file {}'.format(os.path.basename(filename))) + non_whitelisted_msg = ('Non-Whitelisted IDs {} found in {}' + .format(non_whitelisted_ids_found, os.path.basename(filename))) + self.assertFalse(non_whitelisted_ids_found, non_whitelisted_msg) + + def testWhitelistStrings(self): + output_dir = tempfile.mkdtemp() + builder = build.RcBuilder() + class DummyOpts(object): + def __init__(self): + self.input = util.PathFromRoot('grit/testdata/whitelist_strings.grd') + self.verbose = False + self.extra_verbose = False + whitelist_file = util.PathFromRoot('grit/testdata/whitelist.txt') + builder.Run(DummyOpts(), ['-o', output_dir, + '-w', whitelist_file]) + header = os.path.join(output_dir, 'whitelist_test_resources.h') + rc = os.path.join(output_dir, 'en_whitelist_test_strings.rc') + + whitelisted_ids = ['IDS_MESSAGE_WHITELISTED'] + non_whitelisted_ids = ['IDS_MESSAGE_NOT_WHITELISTED'] + self._verifyWhitelistedOutput( + header, + whitelisted_ids, + non_whitelisted_ids, + ) + self._verifyWhitelistedOutput( + rc, + whitelisted_ids, + non_whitelisted_ids, + encoding='utf16' + ) + + def testWhitelistResources(self): + output_dir = tempfile.mkdtemp() + builder = build.RcBuilder() + class DummyOpts(object): + def __init__(self): + self.input = util.PathFromRoot('grit/testdata/whitelist_resources.grd') + self.verbose = False + self.extra_verbose = False + whitelist_file = util.PathFromRoot('grit/testdata/whitelist.txt') + builder.Run(DummyOpts(), ['-o', output_dir, + '-w', whitelist_file]) + header = os.path.join(output_dir, 'whitelist_test_resources.h') + map_cc = os.path.join(output_dir, 'whitelist_test_resources_map.cc') + map_h = os.path.join(output_dir, 'whitelist_test_resources_map.h') + pak = os.path.join(output_dir, 'whitelist_test_resources.pak') + + # Ensure the resource map header and .pak files exist, but don't verify + # their content. + self.failUnless(os.path.exists(map_h)) + self.failUnless(os.path.exists(pak)) + + whitelisted_ids = [ + 'IDR_STRUCTURE_WHITELISTED', + 'IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED', + 'IDR_INCLUDE_WHITELISTED', + ] + non_whitelisted_ids = [ + 'IDR_STRUCTURE_NOT_WHITELISTED', + 'IDR_STRUCTURE_IN_TRUE_IF_NOT_WHITELISTED', + 'IDR_STRUCTURE_IN_FALSE_IF_WHITELISTED', + 'IDR_STRUCTURE_IN_FALSE_IF_NOT_WHITELISTED', + 'IDR_INCLUDE_NOT_WHITELISTED', + ] + for output_file in (header, map_cc): + self._verifyWhitelistedOutput( + output_file, + whitelisted_ids, + non_whitelisted_ids, + ) + + def testOutputAllResourceDefinesTrue(self): + output_dir = tempfile.mkdtemp() + builder = build.RcBuilder() + class DummyOpts(object): + def __init__(self): + self.input = util.PathFromRoot('grit/testdata/whitelist_resources.grd') + self.verbose = False + self.extra_verbose = False + whitelist_file = util.PathFromRoot('grit/testdata/whitelist.txt') + builder.Run(DummyOpts(), ['-o', output_dir, + '-w', whitelist_file, + '--output-all-resource-defines',]) + header = os.path.join(output_dir, 'whitelist_test_resources.h') + map_cc = os.path.join(output_dir, 'whitelist_test_resources_map.cc') + + whitelisted_ids = [ + 'IDR_STRUCTURE_WHITELISTED', + 'IDR_STRUCTURE_NOT_WHITELISTED', + 'IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED', + 'IDR_STRUCTURE_IN_TRUE_IF_NOT_WHITELISTED', + 'IDR_STRUCTURE_IN_FALSE_IF_WHITELISTED', + 'IDR_STRUCTURE_IN_FALSE_IF_NOT_WHITELISTED', + 'IDR_INCLUDE_WHITELISTED', + 'IDR_INCLUDE_NOT_WHITELISTED', + ] + non_whitelisted_ids = [] + for output_file in (header, map_cc): + self._verifyWhitelistedOutput( + output_file, + whitelisted_ids, + non_whitelisted_ids, + ) + + def testOutputAllResourceDefinesFalse(self): + output_dir = tempfile.mkdtemp() + builder = build.RcBuilder() + class DummyOpts(object): + def __init__(self): + self.input = util.PathFromRoot('grit/testdata/whitelist_resources.grd') + self.verbose = False + self.extra_verbose = False + whitelist_file = util.PathFromRoot('grit/testdata/whitelist.txt') + builder.Run(DummyOpts(), ['-o', output_dir, + '-w', whitelist_file, + '--no-output-all-resource-defines',]) + header = os.path.join(output_dir, 'whitelist_test_resources.h') + map_cc = os.path.join(output_dir, 'whitelist_test_resources_map.cc') + + whitelisted_ids = [ + 'IDR_STRUCTURE_WHITELISTED', + 'IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED', + 'IDR_INCLUDE_WHITELISTED', + ] + non_whitelisted_ids = [ + 'IDR_STRUCTURE_NOT_WHITELISTED', + 'IDR_STRUCTURE_IN_TRUE_IF_NOT_WHITELISTED', + 'IDR_STRUCTURE_IN_FALSE_IF_WHITELISTED', + 'IDR_STRUCTURE_IN_FALSE_IF_NOT_WHITELISTED', + 'IDR_INCLUDE_NOT_WHITELISTED', + ] + for output_file in (header, map_cc): + self._verifyWhitelistedOutput( + output_file, + whitelisted_ids, + non_whitelisted_ids, + ) + + if __name__ == '__main__': unittest.main() diff --git a/grit_info.py b/grit_info.py index 47a51f7..ce52997 100755 --- a/grit_info.py +++ b/grit_info.py @@ -112,6 +112,12 @@ def DoMain(argv): # line flags. parser.add_option("-E", action="append", dest="build_env", default=[]) parser.add_option("-w", action="append", dest="whitelist_files", default=[]) + parser.add_option("--output-all-resource-defines", action="store_true", + dest="output_all_resource_defines", default=True, + help="Unused") + parser.add_option("--no-output-all-resource-defines", action="store_false", + dest="output_all_resource_defines", default=True, + help="Unused") parser.add_option("-f", dest="ids_file", default="GRIT_DIR/../gritsettings/resource_ids") parser.add_option("-t", dest="target_platform", default=None) |