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.orgfrom xml.dom import minidom
701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom grit.format.policy_templates.writers import xml_formatted_writer
801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
1001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgdef GetWriter(config):
1101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  '''Factory method for instanciating the ADMXWriter. Every Writer needs a
1201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  GetWriter method because the TemplateFormatter uses this method to
1301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  instantiate a Writer.
1401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  '''
1501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  return ADMXWriter(['win'], config)
1601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
1701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
1801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgclass ADMXWriter(xml_formatted_writer.XMLFormattedWriter):
1901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  '''Class for generating an ADMX policy template. It is used by the
2001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  PolicyTemplateGenerator to write the admx file.
2101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  '''
2201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
2301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  # DOM root node of the generated ADMX document.
2401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  _doc = None
2501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
2601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  # The ADMX "policies" element that contains the ADMX "policy" elements that
2701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  # are generated.
2801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  _active_policies_elem = None
2901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
3001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def _AdmlString(self, name):
3101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Creates a reference to the named string in an ADML file.
3201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    Args:
3301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      name: Name of the referenced ADML string.
3401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
3501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    return '$(string.' + name + ')'
3601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
3701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def _AdmlStringExplain(self, name):
3801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Creates a reference to the named explanation string in an ADML file.
3901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    Args:
4001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      name: Name of the referenced ADML explanation.
4101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
4201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    return '$(string.' + name + '_Explain)'
4301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
4401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def _AdmlPresentation(self, name):
4501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Creates a reference to the named presentation element in an ADML file.
4601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    Args:
4701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      name: Name of the referenced ADML presentation element.
4801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
4901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    return '$(presentation.' + name + ')'
5001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
5101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def _AddPolicyNamespaces(self, parent, prefix, namespace):
5201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Generates the ADMX "policyNamespace" element and adds the elements to the
5301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    passed parent element. The namespace of the generated ADMX document is
5401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    define via the ADMX "target" element. Used namespaces are declared with an
5501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    ADMX "using" element. ADMX "target" and "using" elements are children of the
5601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    ADMX "policyNamespace" element.
5701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
5801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    Args:
5901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      parent: The parent node to which all generated elements are added.
6001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      prefix: A logical name that can be used in the generated ADMX document to
6101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        refere to this namespace.
6201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      namespace: Namespace of the generated ADMX document.
6301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
6401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    policy_namespaces_elem = self.AddElement(parent, 'policyNamespaces')
6501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    attributes = {
6601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'prefix': prefix,
6701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'namespace': namespace,
6801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    }
6901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(policy_namespaces_elem, 'target', attributes)
7001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    attributes = {
7101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'prefix': 'windows',
7201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'namespace': 'Microsoft.Policies.Windows',
7301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    }
7401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(policy_namespaces_elem, 'using', attributes)
7501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
7601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def _AddCategory(self, parent, name, display_name,
7701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                   parent_category_name=None):
7801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Adds an ADMX category element to the passed parent node. The following
7901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    snippet shows an example of a category element where "chromium" is the value
8001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    of the parameter name:
8101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
8201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    <category displayName="$(string.chromium)" name="chromium"/>
8301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
841ab22a47727a765d94f9d2ee142cbd8d709849e2joaodasilva@chromium.org    Each parent node can have only one category with a given name. Adding the
851ab22a47727a765d94f9d2ee142cbd8d709849e2joaodasilva@chromium.org    same category again with the same attributes is ignored, but adding it
861ab22a47727a765d94f9d2ee142cbd8d709849e2joaodasilva@chromium.org    again with different attributes is an error.
871ab22a47727a765d94f9d2ee142cbd8d709849e2joaodasilva@chromium.org
8801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    Args:
8901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      parent: The parent node to which all generated elements are added.
9001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      name: Name of the category.
9101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      display_name: Display name of the category.
9201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      parent_category_name: Name of the parent category. Defaults to None.
9301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
941ab22a47727a765d94f9d2ee142cbd8d709849e2joaodasilva@chromium.org    existing = filter(lambda e: e.getAttribute('name') == name,
951ab22a47727a765d94f9d2ee142cbd8d709849e2joaodasilva@chromium.org                      parent.getElementsByTagName('category'))
961ab22a47727a765d94f9d2ee142cbd8d709849e2joaodasilva@chromium.org    if existing:
971ab22a47727a765d94f9d2ee142cbd8d709849e2joaodasilva@chromium.org      assert len(existing) == 1
981ab22a47727a765d94f9d2ee142cbd8d709849e2joaodasilva@chromium.org      assert existing[0].getAttribute('name') == name
991ab22a47727a765d94f9d2ee142cbd8d709849e2joaodasilva@chromium.org      assert existing[0].getAttribute('displayName') == display_name
1001ab22a47727a765d94f9d2ee142cbd8d709849e2joaodasilva@chromium.org      return
10101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    attributes = {
10201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'name': name,
10301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'displayName': display_name,
10401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    }
10501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    category_elem = self.AddElement(parent, 'category', attributes)
10601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    if parent_category_name:
10701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      attributes = {'ref': parent_category_name}
10801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      self.AddElement(category_elem, 'parentCategory', attributes)
10901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
1100bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org  def _AddCategories(self, categories):
1110bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    '''Generates the ADMX "categories" element and adds it to the categories
1120bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    main node. The "categories" element defines the category for the policies
1130bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    defined in this ADMX document. Here is an example of an ADMX "categories"
1140bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    element:
11501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
11601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    <categories>
11701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      <category displayName="$(string.google)" name="google"/>
11801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      <category displayName="$(string.googlechrome)" name="googlechrome">
11901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        <parentCategory ref="google"/>
12001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      </category>
12101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    </categories>
12201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
12301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    Args:
12401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      categories_path: The categories path e.g. ['google', 'googlechrome']. For
12501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        each level in the path a "category" element will be generated. Except
12601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        for the root level, each level refers to its parent. Since the root
12701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        level category has no parent it does not require a parent reference.
12801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
12901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    category_name = None
13001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    for category in categories:
13101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      parent_category_name = category_name
13201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      category_name = category
13301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      self._AddCategory(self._categories_elem, category_name,
13401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                        self._AdmlString(category_name), parent_category_name)
13501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
13601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def _AddSupportedOn(self, parent, supported_os):
13701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Generates the "supportedOn" ADMX element and adds it to the passed
13801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    parent node. The "supportedOn" element contains information about supported
13901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    Windows OS versions. The following code snippet contains an example of a
14001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    "supportedOn" element:
14101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
14201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    <supportedOn>
14301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      <definitions>
14401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        <definition name="SUPPORTED_WINXPSP2"
14501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                    displayName="$(string.SUPPORTED_WINXPSP2)"/>
14601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        </definitions>
14701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        ...
14801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    </supportedOn>
14901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
15001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    Args:
15101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      parent: The parent element to which all generated elements are added.
15201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      supported_os: List with all supported Win OSes.
15301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
15401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    supported_on_elem = self.AddElement(parent, 'supportedOn')
15501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    definitions_elem = self.AddElement(supported_on_elem, 'definitions')
15601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    attributes = {
15701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'name': supported_os,
15801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'displayName': self._AdmlString(supported_os)
15901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    }
16001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(definitions_elem, 'definition', attributes)
16101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
16201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def _AddStringPolicy(self, parent, name):
16301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Generates ADMX elements for a String-Policy and adds them to the
16401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    passed parent node.
16501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
16601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    attributes = {
16701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'id': name,
16801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'valueName': name,
16901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    }
17001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(parent, 'text', attributes)
17101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
17201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def _AddIntPolicy(self, parent, name):
17301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Generates ADMX elements for an Int-Policy and adds them to the passed
17401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    parent node.
17501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
17601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    attributes = {
17701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'id': name,
17801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'valueName': name,
1799286469aaa9be3f2bef0156a27faf105b8d55449pastarmovj@chromium.org      'maxValue': '2000000000',
18001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    }
18101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(parent, 'decimal', attributes)
18201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
18301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def _AddEnumPolicy(self, parent, policy):
18401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Generates ADMX elements for an Enum-Policy and adds them to the
18501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    passed parent element.
18601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
18701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    name = policy['name']
18801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    items = policy['items']
18901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    attributes = {
19001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'id': name,
19101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'valueName': name,
19201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    }
19301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    enum_elem = self.AddElement(parent, 'enum', attributes)
19401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    for item in items:
19501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      attributes = {'displayName': self._AdmlString(item['name'])}
19601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      item_elem = self.AddElement(enum_elem, 'item', attributes)
19701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      value_elem = self.AddElement(item_elem, 'value')
19801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      value_string = str(item['value'])
19901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      if policy['type'] == 'int-enum':
20001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        self.AddElement(value_elem, 'decimal', {'value': value_string})
20101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      else:
20201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        self.AddElement(value_elem, 'string', {}, value_string)
20301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
2040bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org  def _AddListPolicy(self, parent, key, name):
20501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Generates ADMX XML elements for a List-Policy and adds them to the
20601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    passed parent element.
20701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
20801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    attributes = {
20901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      # The ID must be in sync with ID of the corresponding element in the ADML
21001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      # file.
21101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'id': name + 'Desc',
21201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'valuePrefix': '',
2130bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org      'key': key + '\\' + name,
21401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    }
21501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(parent, 'list', attributes)
21601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
21701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def _AddMainPolicy(self, parent):
21801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Generates ADMX elements for a Main-Policy amd adds them to the
21901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    passed parent element.
22001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
22101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    enabled_value_elem = self.AddElement(parent, 'enabledValue');
22201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(enabled_value_elem, 'decimal', {'value': '1'})
22301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    disabled_value_elem = self.AddElement(parent, 'disabledValue');
22401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(disabled_value_elem, 'decimal', {'value': '0'})
22501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
22601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def _GetElements(self, policy_group_elem):
22701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Returns the ADMX "elements" child from an ADMX "policy" element. If the
22801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    "policy" element has no "elements" child yet, a new child is created.
22901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
23001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    Args:
23101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      policy_group_elem: The ADMX "policy" element from which the child element
23201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org        "elements" is returned.
23301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
23401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    Raises:
23501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      Exception: The policy_group_elem does not contain a ADMX "policy" element.
23601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
23701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    if policy_group_elem.tagName != 'policy':
23801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      raise Exception('Expected a "policy" element but got a "%s" element'
23901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                      % policy_group_elem.tagName)
24001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    elements_list = policy_group_elem.getElementsByTagName('elements');
24101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    if len(elements_list) == 0:
24201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      return self.AddElement(policy_group_elem, 'elements')
24301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    elif len(elements_list) == 1:
24401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      return elements_list[0]
24501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    else:
24601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      raise Exception('There is supposed to be only one "elements" node but'
24701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                      ' there are %s.' % str(len(elements_list)))
24801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
2490bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org  def _WritePolicy(self, policy, name, key, parent):
25001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Generates AMDX elements for a Policy. There are four different policy
25101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    types: Main-Policy, String-Policy, Enum-Policy and List-Policy.
25201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
25301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    policies_elem = self._active_policies_elem
25401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    policy_type = policy['type']
25501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    policy_name = policy['name']
256e9f965b7a19bfc970bec100fb03e6aa269deb522joaodasilva@chromium.org    if policy_type == 'external':
257e9f965b7a19bfc970bec100fb03e6aa269deb522joaodasilva@chromium.org      # This type can only be set through cloud policy.
258e9f965b7a19bfc970bec100fb03e6aa269deb522joaodasilva@chromium.org      return
25901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
26001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    attributes = {
2610bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org      'name': name,
26201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'class': self.config['win_group_policy_class'],
26301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'displayName': self._AdmlString(policy_name),
26401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'explainText': self._AdmlStringExplain(policy_name),
26501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      'presentation': self._AdmlPresentation(policy_name),
2660bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org      'key': key,
26701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    }
26801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    # Store the current "policy" AMDX element in self for later use by the
26901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    # WritePolicy method.
27001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    policy_elem = self.AddElement(policies_elem, 'policy',
27101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                                  attributes)
27201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(policy_elem, 'parentCategory',
2730bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org                    {'ref': parent})
27401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(policy_elem, 'supportedOn',
27501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                    {'ref': self.config['win_supported_os']})
27601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    if policy_type == 'main':
27701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      self.AddAttribute(policy_elem, 'valueName', policy_name)
27801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      self._AddMainPolicy(policy_elem)
279248837b02a1e8da230541fa6c12e4d1b1dea2701joaodasilva@chromium.org    elif policy_type in ('string', 'dict'):
280248837b02a1e8da230541fa6c12e4d1b1dea2701joaodasilva@chromium.org      # 'dict' policies are configured as JSON-encoded strings on Windows.
28101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      parent = self._GetElements(policy_elem)
28201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      self._AddStringPolicy(parent, policy_name)
28301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    elif policy_type == 'int':
28401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      parent = self._GetElements(policy_elem)
28501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      self._AddIntPolicy(parent, policy_name)
28601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    elif policy_type in ('int-enum', 'string-enum'):
28701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      parent = self._GetElements(policy_elem)
28801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      self._AddEnumPolicy(parent, policy)
289786be15cb6c0f7d78f3eab9fda9d4266619ddbf0joaodasilva@chromium.org    elif policy_type in ('list', 'string-enum-list'):
29001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      parent = self._GetElements(policy_elem)
2910bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org      self._AddListPolicy(parent, key, policy_name)
29201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    elif policy_type == 'group':
29301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      pass
29401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    else:
29501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org      raise Exception('Unknown policy type %s.' % policy_type)
29601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
2970bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org  def WritePolicy(self, policy):
298740badd5e3e44434a9a47b5d16749daac1e8ea80joaodasilva@chromium.org    if self.CanBeMandatory(policy):
299740badd5e3e44434a9a47b5d16749daac1e8ea80joaodasilva@chromium.org      self._WritePolicy(policy,
300740badd5e3e44434a9a47b5d16749daac1e8ea80joaodasilva@chromium.org                        policy['name'],
301740badd5e3e44434a9a47b5d16749daac1e8ea80joaodasilva@chromium.org                        self.config['win_reg_mandatory_key_name'],
302740badd5e3e44434a9a47b5d16749daac1e8ea80joaodasilva@chromium.org                        self._active_mandatory_policy_group_name)
3030bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org
3040bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org  def WriteRecommendedPolicy(self, policy):
3050bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    self._WritePolicy(policy,
3060bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org                      policy['name'] + '_recommended',
3070bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org                      self.config['win_reg_recommended_key_name'],
3080bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org                      self._active_recommended_policy_group_name)
3090bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org
3100bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org  def _BeginPolicyGroup(self, group, name, parent):
31101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Generates ADMX elements for a Policy-Group.
31201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
31301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    attributes = {
3140bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org      'name': name,
3150bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org      'displayName': self._AdmlString(group['name'] + '_group'),
31601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    }
31701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    category_elem = self.AddElement(self._categories_elem,
31801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                                    'category',
31901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                                    attributes)
32001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    attributes = {
3210bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org      'ref': parent
32201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    }
32301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(category_elem, 'parentCategory', attributes)
3240bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org
3250bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org  def BeginPolicyGroup(self, group):
3260bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    self._BeginPolicyGroup(group,
3270bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org                           group['name'],
3280bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org                           self.config['win_mandatory_category_path'][-1])
3290bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    self._active_mandatory_policy_group_name = group['name']
33001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
33101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def EndPolicyGroup(self):
3320bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    self._active_mandatory_policy_group_name = \
3330bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org        self.config['win_mandatory_category_path'][-1]
3340bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org
3350bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org  def BeginRecommendedPolicyGroup(self, group):
3360bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    self._BeginPolicyGroup(group,
3370bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org                           group['name'] + '_recommended',
3380bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org                           self.config['win_recommended_category_path'][-1])
3390bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    self._active_recommended_policy_group_name = group['name'] + '_recommended'
3400bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org
3410bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org  def EndRecommendedPolicyGroup(self):
3420bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    self._active_recommended_policy_group_name = \
3430bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org        self.config['win_recommended_category_path'][-1]
34401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
34501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def BeginTemplate(self):
34601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''Generates the skeleton of the ADMX template. An ADMX template contains
34701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    an ADMX "PolicyDefinitions" element with four child nodes: "policies"
34801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    "policyNamspaces", "resources", "supportedOn" and "categories"
34901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    '''
35001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    dom_impl = minidom.getDOMImplementation('')
35101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._doc = dom_impl.createDocument(None, 'policyDefinitions', None)
35201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    policy_definitions_elem = self._doc.documentElement
35301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
35401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    policy_definitions_elem.attributes['revision'] = '1.0'
35501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    policy_definitions_elem.attributes['schemaVersion'] = '1.0'
35601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
35701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._AddPolicyNamespaces(policy_definitions_elem,
35801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                              self.config['admx_prefix'],
35901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                              self.config['admx_namespace'])
36001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self.AddElement(policy_definitions_elem, 'resources',
36101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                    {'minRequiredRevision' : '1.0'})
36201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._AddSupportedOn(policy_definitions_elem,
36301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                         self.config['win_supported_os'])
3640bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    self._categories_elem = self.AddElement(policy_definitions_elem,
3650bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org                                            'categories')
3660bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    self._AddCategories(self.config['win_mandatory_category_path'])
3670bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    self._AddCategories(self.config['win_recommended_category_path'])
36801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    self._active_policies_elem = self.AddElement(policy_definitions_elem,
36901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org                                                 'policies')
3700bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    self._active_mandatory_policy_group_name = \
3710bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org        self.config['win_mandatory_category_path'][-1]
3720bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org    self._active_recommended_policy_group_name = \
3730bb959423818266efea82162f48ad83e5eb2e8b2joaodasilva@chromium.org        self.config['win_recommended_category_path'][-1]
37401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org
37501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org  def GetTemplateText(self):
37601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org    return self.ToPrettyXml(self._doc)
377