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
7import copy
8
9
10class PolicyTemplateGenerator:
11  '''Generates template text for a particular platform.
12
13  This class is used to traverse a JSON structure from a .json template
14  definition metafile and merge GUI message string definitions that come
15  from a .grd resource tree onto it. After this, it can be used to output
16  this data to policy template files using TemplateWriter objects.
17  '''
18
19  def _ImportMessage(self, msg_txt):
20    msg_txt = msg_txt.decode('utf-8')
21    # Replace the placeholder of app name.
22    msg_txt = msg_txt.replace('$1', self._config['app_name'])
23    msg_txt = msg_txt.replace('$2', self._config['os_name'])
24    msg_txt = msg_txt.replace('$3', self._config['frame_name'])
25    # Strip spaces and escape newlines.
26    lines = msg_txt.split('\n')
27    lines = [line.strip() for line in lines]
28    return "\n".join(lines)
29
30  def __init__(self, config, policy_data):
31    '''Initializes this object with all the data necessary to output a
32    policy template.
33
34    Args:
35      messages: An identifier to string dictionary of all the localized
36        messages that might appear in the policy template.
37      policy_definitions: The list of defined policies and groups, as
38        parsed from the policy metafile. Note that this list is passed by
39        reference and its contents are modified.
40        See chrome/app/policy.policy_templates.json for description and
41        content.
42    '''
43    # List of all the policies:
44    self._policy_data = copy.deepcopy(policy_data)
45    # Localized messages to be inserted to the policy_definitions structure:
46    self._messages = self._policy_data['messages']
47    self._config = config
48    for key in self._messages.keys():
49      self._messages[key]['text'] = self._ImportMessage(
50          self._messages[key]['text'])
51    self._policy_definitions = self._policy_data['policy_definitions']
52    self._ProcessPolicyList(self._policy_definitions)
53
54  def _ProcessSupportedOn(self, supported_on):
55    '''Parses and converts the string items of the list of supported platforms
56    into dictionaries.
57
58    Args:
59      supported_on: The list of supported platforms. E.g.:
60        ['chrome.win:8-10', 'chrome_frame:10-']
61
62    Returns:
63      supported_on: The list with its items converted to dictionaries. E.g.:
64      [{
65        'product': 'chrome',
66        'platform': 'win',
67        'since_version': '8',
68        'until_version': '10'
69      }, {
70        'product': 'chrome_frame',
71        'platform': 'win',
72        'since_version': '10',
73        'until_version': ''
74      }]
75    '''
76    result = []
77    for supported_on_item in supported_on:
78      product_platform_part, version_part = supported_on_item.split(':')
79
80      if '.' in product_platform_part:
81        product, platform = product_platform_part.split('.')
82        if platform == '*':
83          # e.g.: 'chrome.*:8-10'
84          platforms = ['linux', 'mac', 'win']
85        else:
86          # e.g.: 'chrome.win:-10'
87          platforms = [platform]
88      else:
89        # e.g.: 'chrome_frame:7-'
90        product, platform = {
91          'android':      ('chrome',        'android'),
92          'chrome_os':    ('chrome_os',     'chrome_os'),
93          'chrome_frame': ('chrome_frame',  'win'),
94          'ios':          ('chrome',        'ios'),
95        }[product_platform_part]
96        platforms = [platform]
97      since_version, until_version = version_part.split('-')
98      result.append({
99        'product': product,
100        'platforms': platforms,
101        'since_version': since_version,
102        'until_version': until_version
103      })
104    return result
105
106  def _ProcessPolicy(self, policy):
107    '''Processes localized message strings in a policy or a group.
108     Also breaks up the content of 'supported_on' attribute into a list.
109
110    Args:
111      policy: The data structure of the policy or group, that will get message
112        strings here.
113    '''
114    policy['desc'] = self._ImportMessage(policy['desc'])
115    policy['caption'] = self._ImportMessage(policy['caption'])
116    if 'label' in policy:
117      policy['label'] = self._ImportMessage(policy['label'])
118
119    if policy['type'] == 'group':
120      self._ProcessPolicyList(policy['policies'])
121    elif policy['type'] in ('string-enum', 'int-enum', 'string-enum-list'):
122      # Iterate through all the items of an enum-type policy, and add captions.
123      for item in policy['items']:
124        item['caption'] = self._ImportMessage(item['caption'])
125    if policy['type'] != 'group':
126      if not 'label' in policy:
127        # If 'label' is not specified, then it defaults to 'caption':
128        policy['label'] = policy['caption']
129      policy['supported_on'] = self._ProcessSupportedOn(policy['supported_on'])
130
131  def _ProcessPolicyList(self, policy_list):
132    '''Adds localized message strings to each item in a list of policies and
133    groups. Also breaks up the content of 'supported_on' attributes into lists
134    of dictionaries.
135
136    Args:
137      policy_list: A list of policies and groups. Message strings will be added
138        for each item and to their child items, recursively.
139    '''
140    for policy in policy_list:
141      self._ProcessPolicy(policy)
142
143  def GetTemplateText(self, template_writer):
144    '''Generates the text of the template from the arguments given
145    to the constructor, using a given TemplateWriter.
146
147    Args:
148      template_writer: An object implementing TemplateWriter. Its methods
149        are called here for each item of self._policy_groups.
150
151    Returns:
152      The text of the generated template.
153    '''
154    return template_writer.WriteTemplate(self._policy_data)
155