1#!/usr/bin/env python 2# Copyright (c) 2012 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6 7from xml.dom import minidom 8from grit.format.policy_templates.writers import plist_helper 9from grit.format.policy_templates.writers import xml_formatted_writer 10 11 12# This writer outputs a Preferences Manifest file as documented at 13# https://developer.apple.com/library/mac/documentation/MacOSXServer/Conceptual/Preference_Manifest_Files 14 15 16def GetWriter(config): 17 '''Factory method for creating PListWriter objects. 18 See the constructor of TemplateWriter for description of 19 arguments. 20 ''' 21 return PListWriter(['mac'], config) 22 23 24class PListWriter(xml_formatted_writer.XMLFormattedWriter): 25 '''Class for generating policy templates in Mac plist format. 26 It is used by PolicyTemplateGenerator to write plist files. 27 ''' 28 29 STRING_TABLE = 'Localizable.strings' 30 TYPE_TO_INPUT = { 31 'string': 'string', 32 'int': 'integer', 33 'int-enum': 'integer', 34 'string-enum': 'string', 35 'string-enum-list': 'array', 36 'main': 'boolean', 37 'list': 'array', 38 'dict': 'dictionary', 39 } 40 41 def _AddKeyValuePair(self, parent, key_string, value_tag): 42 '''Adds a plist key-value pair to a parent XML element. 43 44 A key-value pair in plist consists of two XML elements next two each other: 45 <key>key_string</key> 46 <value_tag>...</value_tag> 47 48 Args: 49 key_string: The content of the key tag. 50 value_tag: The name of the value element. 51 52 Returns: 53 The XML element of the value tag. 54 ''' 55 self.AddElement(parent, 'key', {}, key_string) 56 return self.AddElement(parent, value_tag) 57 58 def _AddStringKeyValuePair(self, parent, key_string, value_string): 59 '''Adds a plist key-value pair to a parent XML element, where the 60 value element contains a string. The name of the value element will be 61 <string>. 62 63 Args: 64 key_string: The content of the key tag. 65 value_string: The content of the value tag. 66 ''' 67 self.AddElement(parent, 'key', {}, key_string) 68 self.AddElement(parent, 'string', {}, value_string) 69 70 def _AddTargets(self, parent, policy): 71 '''Adds the following XML snippet to an XML element: 72 <key>pfm_targets</key> 73 <array> 74 <string>user-managed</string> 75 </array> 76 77 Args: 78 parent: The parent XML element where the snippet will be added. 79 ''' 80 array = self._AddKeyValuePair(parent, 'pfm_targets', 'array') 81 if self.CanBeRecommended(policy): 82 self.AddElement(array, 'string', {}, 'user') 83 if self.CanBeMandatory(policy): 84 self.AddElement(array, 'string', {}, 'user-managed') 85 86 def PreprocessPolicies(self, policy_list): 87 return self.FlattenGroupsAndSortPolicies(policy_list) 88 89 def WritePolicy(self, policy): 90 policy_name = policy['name'] 91 policy_type = policy['type'] 92 if policy_type == 'external': 93 # This type can only be set through cloud policy. 94 return 95 96 dict = self.AddElement(self._array, 'dict') 97 self._AddStringKeyValuePair(dict, 'pfm_name', policy_name) 98 # Set empty strings for title and description. They will be taken by the 99 # OSX Workgroup Manager from the string table in a Localizable.strings file. 100 # Those files are generated by plist_strings_writer. 101 self._AddStringKeyValuePair(dict, 'pfm_description', '') 102 self._AddStringKeyValuePair(dict, 'pfm_title', '') 103 self._AddTargets(dict, policy) 104 self._AddStringKeyValuePair(dict, 'pfm_type', 105 self.TYPE_TO_INPUT[policy_type]) 106 if policy_type in ('int-enum', 'string-enum'): 107 range_list = self._AddKeyValuePair(dict, 'pfm_range_list', 'array') 108 for item in policy['items']: 109 if policy_type == 'int-enum': 110 element_type = 'integer' 111 else: 112 element_type = 'string' 113 self.AddElement(range_list, element_type, {}, str(item['value'])) 114 elif policy_type in ('list', 'string-enum-list'): 115 subkeys = self._AddKeyValuePair(dict, 'pfm_subkeys', 'array') 116 subkeys_dict = self.AddElement(subkeys, 'dict') 117 subkeys_type = self._AddKeyValuePair(subkeys_dict, 'pfm_type', 'string') 118 self.AddText(subkeys_type, 'string') 119 120 def BeginTemplate(self): 121 self._plist.attributes['version'] = '1' 122 dict = self.AddElement(self._plist, 'dict') 123 124 app_name = plist_helper.GetPlistFriendlyName(self.config['app_name']) 125 self._AddStringKeyValuePair(dict, 'pfm_name', app_name) 126 self._AddStringKeyValuePair(dict, 'pfm_description', '') 127 self._AddStringKeyValuePair(dict, 'pfm_title', '') 128 self._AddStringKeyValuePair(dict, 'pfm_version', '1') 129 self._AddStringKeyValuePair(dict, 'pfm_domain', 130 self.config['mac_bundle_id']) 131 132 self._array = self._AddKeyValuePair(dict, 'pfm_subkeys', 'array') 133 134 def CreatePlistDocument(self): 135 dom_impl = minidom.getDOMImplementation('') 136 doctype = dom_impl.createDocumentType( 137 'plist', 138 '-//Apple//DTD PLIST 1.0//EN', 139 'http://www.apple.com/DTDs/PropertyList-1.0.dtd') 140 return dom_impl.createDocument(None, 'plist', doctype) 141 142 def Init(self): 143 self._doc = self.CreatePlistDocument() 144 self._plist = self._doc.documentElement 145 146 def GetTemplateText(self): 147 return self.ToPrettyXml(self._doc) 148