195640e3a20adea634b4df4ccf8c93f411184c438joi@chromium.org#!/usr/bin/env python
295640e3a20adea634b4df4ccf8c93f411184c438joi@chromium.org# Copyright (c) 2012 The Chromium Authors. All rights reserved.
301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org# Use of this source code is governed by a BSD-style license that can be
401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org# found in the LICENSE file.
501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom xml.dom import minidom
801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom grit.format.policy_templates.writers import plist_helper
901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom grit.format.policy_templates.writers import xml_formatted_writer
1001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
1101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
1209ac06a38baa2cf86f4862bbd1c0e6d92d130bf2joaodasilva@chromium.org# This writer outputs a Preferences Manifest file as documented at
1309ac06a38baa2cf86f4862bbd1c0e6d92d130bf2joaodasilva@chromium.org# https://developer.apple.com/library/mac/documentation/MacOSXServer/Conceptual/Preference_Manifest_Files
1409ac06a38baa2cf86f4862bbd1c0e6d92d130bf2joaodasilva@chromium.org
1509ac06a38baa2cf86f4862bbd1c0e6d92d130bf2joaodasilva@chromium.org
1601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgdef GetWriter(config):
1701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  '''Factory method for creating PListWriter objects.
1801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  See the constructor of TemplateWriter for description of
1901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  arguments.
2001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  '''
2101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  return PListWriter(['mac'], config)
2201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
2301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
2401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgclass PListWriter(xml_formatted_writer.XMLFormattedWriter):
2501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  '''Class for generating policy templates in Mac plist format.
2601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  It is used by PolicyTemplateGenerator to write plist files.
2701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  '''
2801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
2901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  STRING_TABLE = 'Localizable.strings'
3001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  TYPE_TO_INPUT = {
3101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    'string': 'string',
3201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    'int': 'integer',
3301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    'int-enum': 'integer',
3401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    'string-enum': 'string',
35786be15cb6c0f7d78f3eab9fda9d4266619ddbf0joaodasilva@chromium.org    'string-enum-list': 'array',
3601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    'main': 'boolean',
3701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    'list': 'array',
38248837b02a1e8da230541fa6c12e4d1b1dea2701joaodasilva@chromium.org    'dict': 'dictionary',
3901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  }
4001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
4101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def _AddKeyValuePair(self, parent, key_string, value_tag):
4201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Adds a plist key-value pair to a parent XML element.
4301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
4401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    A key-value pair in plist consists of two XML elements next two each other:
4501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    <key>key_string</key>
4601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    <value_tag>...</value_tag>
4701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
4801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    Args:
4901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      key_string: The content of the key tag.
5001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      value_tag: The name of the value element.
5101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
5201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    Returns:
5301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      The XML element of the value tag.
5401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
5501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(parent, 'key', {}, key_string)
5601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    return self.AddElement(parent, value_tag)
5701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
5801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def _AddStringKeyValuePair(self, parent, key_string, value_string):
5901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Adds a plist key-value pair to a parent XML element, where the
6001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    value element contains a string. The name of the value element will be
6101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    <string>.
6201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
6301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    Args:
6401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      key_string: The content of the key tag.
6501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      value_string: The content of the value tag.
6601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
6701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(parent, 'key', {}, key_string)
6801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(parent, 'string', {}, value_string)
6901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
70740badd5e3e44434a9a47b5d16749daac1e8ea80joaodasilva@chromium.org  def _AddTargets(self, parent, policy):
7101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Adds the following XML snippet to an XML element:
7201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      <key>pfm_targets</key>
7301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      <array>
7401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        <string>user-managed</string>
7501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      </array>
7601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
7701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      Args:
7801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        parent: The parent XML element where the snippet will be added.
7901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
8001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    array = self._AddKeyValuePair(parent, 'pfm_targets', 'array')
81740badd5e3e44434a9a47b5d16749daac1e8ea80joaodasilva@chromium.org    if self.CanBeRecommended(policy):
82740badd5e3e44434a9a47b5d16749daac1e8ea80joaodasilva@chromium.org      self.AddElement(array, 'string', {}, 'user')
83740badd5e3e44434a9a47b5d16749daac1e8ea80joaodasilva@chromium.org    if self.CanBeMandatory(policy):
84740badd5e3e44434a9a47b5d16749daac1e8ea80joaodasilva@chromium.org      self.AddElement(array, 'string', {}, 'user-managed')
8501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
8601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def PreprocessPolicies(self, policy_list):
8701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    return self.FlattenGroupsAndSortPolicies(policy_list)
8801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
8901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def WritePolicy(self, policy):
9001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    policy_name = policy['name']
9101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    policy_type = policy['type']
92e9f965b7a19bfc970bec100fb03e6aa269deb522joaodasilva@chromium.org    if policy_type == 'external':
93e9f965b7a19bfc970bec100fb03e6aa269deb522joaodasilva@chromium.org      # This type can only be set through cloud policy.
94e9f965b7a19bfc970bec100fb03e6aa269deb522joaodasilva@chromium.org      return
9501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
9601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    dict = self.AddElement(self._array, 'dict')
9701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._AddStringKeyValuePair(dict, 'pfm_name', policy_name)
9801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    # Set empty strings for title and description. They will be taken by the
9901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    # OSX Workgroup Manager from the string table in a Localizable.strings file.
10001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    # Those files are generated by plist_strings_writer.
10101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._AddStringKeyValuePair(dict, 'pfm_description', '')
10201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._AddStringKeyValuePair(dict, 'pfm_title', '')
103740badd5e3e44434a9a47b5d16749daac1e8ea80joaodasilva@chromium.org    self._AddTargets(dict, policy)
10401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._AddStringKeyValuePair(dict, 'pfm_type',
10501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                                self.TYPE_TO_INPUT[policy_type])
10601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    if policy_type in ('int-enum', 'string-enum'):
10701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      range_list = self._AddKeyValuePair(dict, 'pfm_range_list', 'array')
10801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      for item in policy['items']:
10901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        if policy_type == 'int-enum':
11001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org          element_type = 'integer'
11101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        else:
11201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org          element_type = 'string'
11301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        self.AddElement(range_list, element_type, {}, str(item['value']))
114786be15cb6c0f7d78f3eab9fda9d4266619ddbf0joaodasilva@chromium.org    elif policy_type in ('list', 'string-enum-list'):
11509ac06a38baa2cf86f4862bbd1c0e6d92d130bf2joaodasilva@chromium.org      subkeys = self._AddKeyValuePair(dict, 'pfm_subkeys', 'array')
11609ac06a38baa2cf86f4862bbd1c0e6d92d130bf2joaodasilva@chromium.org      subkeys_dict = self.AddElement(subkeys, 'dict')
11709ac06a38baa2cf86f4862bbd1c0e6d92d130bf2joaodasilva@chromium.org      subkeys_type = self._AddKeyValuePair(subkeys_dict, 'pfm_type', 'string')
11809ac06a38baa2cf86f4862bbd1c0e6d92d130bf2joaodasilva@chromium.org      self.AddText(subkeys_type, 'string')
11901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
12001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def BeginTemplate(self):
12101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._plist.attributes['version'] = '1'
12201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    dict = self.AddElement(self._plist, 'dict')
12301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
12401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    app_name = plist_helper.GetPlistFriendlyName(self.config['app_name'])
12501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._AddStringKeyValuePair(dict, 'pfm_name', app_name)
12601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._AddStringKeyValuePair(dict, 'pfm_description', '')
12701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._AddStringKeyValuePair(dict, 'pfm_title', '')
12801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._AddStringKeyValuePair(dict, 'pfm_version', '1')
12901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._AddStringKeyValuePair(dict, 'pfm_domain',
13001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                                self.config['mac_bundle_id'])
13101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
13201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._array = self._AddKeyValuePair(dict, 'pfm_subkeys', 'array')
13301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
1346fb6d62a2a05b7a7c268cc4e6bf0452e376e1990joaodasilva@chromium.org  def CreatePlistDocument(self):
13501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    dom_impl = minidom.getDOMImplementation('')
13601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    doctype = dom_impl.createDocumentType(
13701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        'plist',
13801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        '-//Apple//DTD PLIST 1.0//EN',
13901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        'http://www.apple.com/DTDs/PropertyList-1.0.dtd')
1406fb6d62a2a05b7a7c268cc4e6bf0452e376e1990joaodasilva@chromium.org    return dom_impl.createDocument(None, 'plist', doctype)
1416fb6d62a2a05b7a7c268cc4e6bf0452e376e1990joaodasilva@chromium.org
1426fb6d62a2a05b7a7c268cc4e6bf0452e376e1990joaodasilva@chromium.org  def Init(self):
1436fb6d62a2a05b7a7c268cc4e6bf0452e376e1990joaodasilva@chromium.org    self._doc = self.CreatePlistDocument()
14401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._plist = self._doc.documentElement
14501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
14601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def GetTemplateText(self):
14701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    return self.ToPrettyXml(self._doc)
148