text: # Copyright (c) 2011 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, parent, id, text):
      ''' Adds an ADML "string" element to the passed parent. 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))
  
    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(self._string_table_elem, policy_name, policy_caption)
      self._AddString(self._string_table_elem, 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 == 'string':
        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})
        label_elem = self.AddElement(textbox_elem, 'label')
        label_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'])
        dropdownlist_elem = self.AddElement(presentation_elem, 'dropdownList',
                                            {'refId': policy_name})
        dropdownlist_elem.appendChild(self._doc.createTextNode(policy_label))
      elif policy_type == 'list':
        self._AddString(self._string_table_elem,
                        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
      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(self._string_table_elem, group['name'] + '_group',
                      group['caption'])
  
    def _AddBaseStrings(self, string_table_elem, 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.messages['win_supported_winxpsp2']['text'])
      if build == 'chrome':
        self._AddString(string_table_elem, self.config['win_category_path'][0],
                        'Google')
        self._AddString(string_table_elem, self.config['win_category_path'][1],
                        self.config['app_name'])
      elif build == 'chromium':
        self._AddString(string_table_elem, self.config['win_category_path'][0],
                        self.config['app_name'])
  
    def BeginTemplate(self):
      dom_impl = minidom.getDOMImplementation('')
      self._doc = dom_impl.createDocument(None, 'policyDefinitionResources',
                                          None)
      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._string_table_elem, self.config['build'])
      self._presentation_table_elem = self.AddElement(resources_elem,
                                                     'presentationTable')
  
    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()
  