aboutsummaryrefslogtreecommitdiff
path: root/grit/format/policy_templates/writers/adml_writer.py
blob: 64f8562ce362c94ce4d6d2e72d4bcdad2560ec61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from xml.dom import minidom
from grit.format.policy_templates.writers import xml_formatted_writer


def GetWriter(config):
  '''Factory method for instanciating the ADMLWriter. Every Writer needs a
  GetWriter method because the TemplateFormatter uses this method to
  instantiate a Writer.
  '''
  return ADMLWriter(['win'], config)


class ADMLWriter(xml_formatted_writer.XMLFormattedWriter):
  ''' Class for generating an ADML policy template. It is used by the
  PolicyTemplateGenerator to write the ADML file.
  '''

  # DOM root node of the generated ADML document.
  _doc = None

  # The string-table contains all ADML "string" elements.
  _string_table_elem = None

  # The presentation-table is the container for presentation elements, that
  # describe the presentation of Policy-Groups and Policies.
  _presentation_table_elem = None

  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:
      id: ID of the newly created "string" element.
      text: Value of the newly created "string" element.
    '''
    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.
    <stringTable>
      ...
      <string id="$(policy_group_name)">$(caption)</string>
      <string id="$(policy_group_name)_Explain">$(description)</string>
    </stringTable>

    <presentationTables>
      ...
      <presentation id=$(policy_group_name)/>
    </presentationTables>

    Args:
      policy: The Policy to generate ADML elements for.
    '''
    policy_type = policy['type']
    policy_name = policy['name']
    if 'caption' in policy:
      policy_caption = policy['caption']
    else:
      policy_caption = policy_name
    if 'desc' in policy:
      policy_description = policy['desc']
    else:
      policy_description = policy_name
    if 'label' in policy:
      policy_label = policy['label']
    else:
      policy_label = policy_name

    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})

    if policy_type == 'main':
      pass
    elif policy_type in ('string', 'dict'):
      # 'dict' policies are configured as JSON-encoded strings on Windows.
      textbox_elem = self.AddElement(presentation_elem, 'textBox',
                                     {'refId': policy_name})
      label_elem = self.AddElement(textbox_elem, 'label')
      label_elem.appendChild(self._doc.createTextNode(policy_label))
    elif policy_type == 'int':
      textbox_elem = self.AddElement(presentation_elem, 'decimalTextBox',
                                     {'refId': policy_name})
      textbox_elem.appendChild(self._doc.createTextNode(policy_label + ':'))
    elif policy_type in ('int-enum', 'string-enum'):
      for item in policy['items']:
        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(policy_name + 'Desc', policy_caption)
      listbox_elem = self.AddElement(presentation_elem, 'listBox',
                                     {'refId': policy_name + 'Desc'})
      listbox_elem.appendChild(self._doc.createTextNode(policy_label))
    elif policy_type == 'group':
      pass
    elif policy_type == 'external':
      # This type can only be set through cloud policy.
      pass
    else:
      raise Exception('Unknown policy type %s.' % policy_type)

  def BeginPolicyGroup(self, group):
    '''Generates ADML elements for a Policy-Group. For each Policy-Group two
    ADML "string" elements are added to the string-table. One contains the
    caption of the Policy-Group and the other a description. A Policy-Group also
    requires an ADML "presentation" element that must be added to the
    presentation-table. The "presentation" element is the container for the
    elements that define the visual presentation of the Policy-Goup's Policies.
    The following ADML snippet shows an example:

    Args:
      group: The Policy-Group to generate ADML elements for.
    '''
    # Add ADML "string" elements to the string-table that are required by a
    # Policy-Group.
    self._AddString(group['name'] + '_group', group['caption'])

  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(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(self.config['win_mandatory_category_path'][0],
                      'Google')
      self._AddString(self.config['win_mandatory_category_path'][1],
                      self.config['app_name'])
      self._AddString(self.config['win_recommended_category_path'][1],
                      recommended_name)
    elif build == 'chromium':
      self._AddString(self.config['win_mandatory_category_path'][0],
                      self.config['app_name'])
      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'

    self.AddElement(policy_definitions_resources_elem, 'displayName')
    self.AddElement(policy_definitions_resources_elem, 'description')
    resources_elem = self.AddElement(policy_definitions_resources_elem,
                                     'resources')
    self._string_table_elem = self.AddElement(resources_elem, 'stringTable')
    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
    # the "string" tags. This prevents gpedit.msc from displaying the category
    # names correctly.
    # TODO(markusheintz): Find a better formatting that works with gpedit.
    return self._doc.toxml()