Improve platform support indications for policy documentation.

The generated policy documentation indicates example values and preferences
paths. This change only shows the data relevant for the platforms where the
policy is actually supported.

BUG=None
R=joi@chromium.org, pastarmovj@chromium.org

Review URL: https://codereview.chromium.org/91233003

git-svn-id: http://grit-i18n.googlecode.com/svn/trunk@139 7262f16d-afe8-6277-6482-052fa10e57b1
diff --git a/grit/format/policy_templates/policy_template_generator.py b/grit/format/policy_templates/policy_template_generator.py
index 2540a72..e742b38 100644
--- a/grit/format/policy_templates/policy_template_generator.py
+++ b/grit/format/policy_templates/policy_template_generator.py
@@ -148,8 +148,7 @@
       if not 'label' in policy:
         # If 'label' is not specified, then it defaults to 'caption':
         policy['label'] = policy['caption']
-      policy['supported_on'] = self._ProcessSupportedOn(
-          policy['supported_on'])
+      policy['supported_on'] = self._ProcessSupportedOn(policy['supported_on'])
 
   def _ProcessPolicyList(self, policy_list):
     '''Adds localized message strings to each item in a list of policies and
diff --git a/grit/format/policy_templates/writers/doc_writer.py b/grit/format/policy_templates/writers/doc_writer.py
index 3876faf..a2f11b4 100644
--- a/grit/format/policy_templates/writers/doc_writer.py
+++ b/grit/format/policy_templates/writers/doc_writer.py
@@ -227,9 +227,12 @@
       policy: The data structure of a policy.
     '''
     examples = self._AddStyledElement(parent, 'dl', ['dd dl'])
-    self._AddListExampleWindows(examples, policy)
-    self._AddListExampleLinux(examples, policy)
-    self._AddListExampleMac(examples, policy)
+    if self.IsPolicySupportedOnPlatform(policy, 'win'):
+      self._AddListExampleWindows(examples, policy)
+    if self.IsPolicySupportedOnPlatform(policy, 'linux'):
+      self._AddListExampleLinux(examples, policy)
+    if self.IsPolicySupportedOnPlatform(policy, 'mac'):
+      self._AddListExampleMac(examples, policy)
 
   def _PythonDictionaryToMacDictionary(self, dictionary, indent=''):
     '''Converts a python dictionary to an equivalent XML plist.
@@ -336,9 +339,12 @@
       policy: The data structure of a policy.
     '''
     examples = self._AddStyledElement(parent, 'dl', ['dd dl'])
-    self._AddDictionaryExampleWindows(examples, policy)
-    self._AddDictionaryExampleLinux(examples, policy)
-    self._AddDictionaryExampleMac(examples, policy)
+    if self.IsPolicySupportedOnPlatform(policy, 'win'):
+      self._AddDictionaryExampleWindows(examples, policy)
+    if self.IsPolicySupportedOnPlatform(policy, 'linux'):
+      self._AddDictionaryExampleLinux(examples, policy)
+    if self.IsPolicySupportedOnPlatform(policy, 'mac'):
+      self._AddDictionaryExampleMac(examples, policy)
 
   def _AddExample(self, parent, policy):
     '''Adds the HTML DOM representation of the example value of a policy to
@@ -358,20 +364,28 @@
     example_value = policy['example_value']
     policy_type = policy['type']
     if policy_type == 'main':
-      if example_value == True:
-        self.AddText(
-            parent, '0x00000001 (Windows), true (Linux), <true /> (Mac)')
-      elif example_value == False:
-        self.AddText(
-            parent, '0x00000000 (Windows), false (Linux), <false /> (Mac)')
-      else:
-        raise Exception('Expected boolean value.')
+      pieces = []
+      if self.IsPolicySupportedOnPlatform(policy, 'win'):
+        value = '0x00000001' if example_value else '0x00000000'
+        pieces.append(value + ' (Windows)')
+      if self.IsPolicySupportedOnPlatform(policy, 'linux'):
+        value = 'true' if example_value else 'false'
+        pieces.append(value + ' (Linux)')
+      if self.IsPolicySupportedOnPlatform(policy, 'mac'):
+        value = '<true />' if example_value else '<false />'
+        pieces.append(value + ' (Mac)')
+      self.AddText(parent, ', '.join(pieces))
     elif policy_type == 'string':
       self.AddText(parent, '"%s"' % example_value)
     elif policy_type in ('int', 'int-enum'):
-      self.AddText(
-          parent,
-          '0x%08x (Windows), %d (Linux/Mac)' % (example_value, example_value))
+      pieces = []
+      if self.IsPolicySupportedOnPlatform(policy, 'win'):
+        pieces.append('0x%08x (Windows)' % example_value)
+      if self.IsPolicySupportedOnPlatform(policy, 'linux'):
+        pieces.append('%d (Linux)' % example_value)
+      if self.IsPolicySupportedOnPlatform(policy, 'mac'):
+        pieces.append('%d (Mac)' % example_value)
+      self.AddText(parent, ', '.join(pieces))
     elif policy_type == 'string-enum':
       self.AddText(parent, '"%s"' % (example_value))
     elif policy_type == 'list':
@@ -445,28 +459,36 @@
     '''
 
     dl = self.AddElement(parent, 'dl')
-    self._AddPolicyAttribute(
-        dl,
-        'data_type',
-        self._TYPE_MAP[policy['type']])
-    self._AddPolicyAttribute(
-        dl,
-        'win_reg_loc',
-        self.config['win_reg_mandatory_key_name'] + '\\' + policy['name'],
-        ['.monospace'])
-    self._AddPolicyAttribute(
-        dl,
-        'mac_linux_pref_name',
-        policy['name'],
-        ['.monospace'])
+    data_type = self._TYPE_MAP[policy['type']]
+    if (self.IsPolicySupportedOnPlatform(policy, 'win') and
+        self._REG_TYPE_MAP.get(policy['type'], None)):
+      data_type += ' (%s)' % self._REG_TYPE_MAP[policy['type']]
+    self._AddPolicyAttribute(dl, 'data_type', data_type)
+    if self.IsPolicySupportedOnPlatform(policy, 'win'):
+      self._AddPolicyAttribute(
+          dl,
+          'win_reg_loc',
+          self.config['win_reg_mandatory_key_name'] + '\\' + policy['name'],
+          ['.monospace'])
+    if (self.IsPolicySupportedOnPlatform(policy, 'linux') or
+        self.IsPolicySupportedOnPlatform(policy, 'mac')):
+      self._AddPolicyAttribute(
+          dl,
+          'mac_linux_pref_name',
+          policy['name'],
+          ['.monospace'])
     dd = self._AddPolicyAttribute(dl, 'supported_on')
     self._AddSupportedOnList(dd, policy['supported_on'])
     dd = self._AddPolicyAttribute(dl, 'supported_features')
     self._AddFeatures(dd, policy)
     dd = self._AddPolicyAttribute(dl, 'description')
     self._AddDescription(dd, policy)
-    dd = self._AddPolicyAttribute(dl, 'example_value')
-    self._AddExample(dd, policy)
+    if (self.IsPolicySupportedOnPlatform(policy, 'win') or
+        self.IsPolicySupportedOnPlatform(policy, 'linux') or
+        self.IsPolicySupportedOnPlatform(policy, 'mac')):
+      # Don't add an example for ChromeOS-only policies.
+      dd = self._AddPolicyAttribute(dl, 'example_value')
+      self._AddExample(dd, policy)
 
   def _AddPolicyNote(self, parent, policy):
     '''If a policy has an additional web page assigned with it, then add
@@ -615,13 +637,21 @@
         self._FEATURE_MAP[message[12:]] = self.messages[message]['text']
     # Human-readable names of types.
     self._TYPE_MAP = {
-      'string': 'String (REG_SZ)',
-      'int': 'Integer (REG_DWORD)',
-      'main': 'Boolean (REG_DWORD)',
-      'int-enum': 'Integer (REG_DWORD)',
-      'string-enum': 'String (REG_SZ)',
+      'string': 'String',
+      'int': 'Integer',
+      'main': 'Boolean',
+      'int-enum': 'Integer',
+      'string-enum': 'String',
       'list': 'List of strings',
-      'dict': 'Dictionary (REG_SZ, encoded as a JSON string)',
+      'dict': 'Dictionary',
+    }
+    self._REG_TYPE_MAP = {
+      'string': 'REG_SZ',
+      'int': 'REG_DWORD',
+      'main': 'REG_DWORD',
+      'int-enum': 'REG_DWORD',
+      'string-enum': 'REG_SZ',
+      'dict': 'REG_SZ, encoded as a JSON string',
     }
     # The CSS style-sheet used for the document. It will be used in Google
     # Sites, which strips class attributes from HTML tags. To work around this,
diff --git a/grit/format/policy_templates/writers/doc_writer_unittest.py b/grit/format/policy_templates/writers/doc_writer_unittest.py
index c413211..96755ca 100644
--- a/grit/format/policy_templates/writers/doc_writer_unittest.py
+++ b/grit/format/policy_templates/writers/doc_writer_unittest.py
@@ -215,7 +215,8 @@
   def testAddListExample(self):
     policy = {
       'name': 'PolicyName',
-      'example_value': ['Foo', 'Bar']
+      'example_value': ['Foo', 'Bar'],
+      'supported_on': [ { 'platforms': ['win', 'mac', 'linux'] } ]
     }
     self.writer._AddListExample(self.doc_root, policy)
     self.assertEquals(
@@ -246,7 +247,8 @@
     policy = {
       'name': 'PolicyName',
       'type': 'main',
-      'example_value': True
+      'example_value': True,
+      'supported_on': [ { 'platforms': ['win', 'mac', 'linux'] } ]
     }
     e1 = self.writer.AddElement(self.doc_root, 'e1')
     self.writer._AddExample(e1, policy)
@@ -257,7 +259,8 @@
     policy = {
       'name': 'PolicyName',
       'type': 'main',
-      'example_value': False
+      'example_value': False,
+      'supported_on': [ { 'platforms': ['win', 'mac', 'linux'] } ]
     }
     e2 = self.writer.AddElement(self.doc_root, 'e2')
     self.writer._AddExample(e2, policy)
@@ -270,12 +273,13 @@
     policy = {
       'name': 'PolicyName',
       'type': 'int-enum',
-      'example_value': 16
+      'example_value': 16,
+      'supported_on': [ { 'platforms': ['win', 'mac', 'linux'] } ]
     }
     self.writer._AddExample(self.doc_root, policy)
     self.assertEquals(
         self.doc_root.toxml(),
-        '<root>0x00000010 (Windows), 16 (Linux/Mac)</root>')
+        '<root>0x00000010 (Windows), 16 (Linux), 16 (Mac)</root>')
 
   def testStringEnumExample(self):
     # Test representation of 'int-enum' example values.
@@ -306,12 +310,13 @@
     policy = {
       'name': 'PolicyName',
       'type': 'int',
-      'example_value': 26
+      'example_value': 26,
+      'supported_on': [ { 'platforms': ['win', 'mac', 'linux'] } ]
     }
     self.writer._AddExample(self.doc_root, policy)
     self.assertEquals(
         self.doc_root.toxml(),
-        '<root>0x0000001a (Windows), 26 (Linux/Mac)</root>')
+        '<root>0x0000001a (Windows), 26 (Linux), 26 (Mac)</root>')
 
   def testAddPolicyAttribute(self):
     # Test creating a policy attribute term-definition pair.
@@ -333,7 +338,7 @@
       'desc': 'TestPolicyDesc',
       'supported_on': [{
         'product': 'chrome',
-        'platforms': ['win'],
+        'platforms': ['win', 'mac', 'linux'],
         'since_version': '8',
         'until_version': '',
       }],
@@ -353,7 +358,7 @@
       '<dt style="style_dt;">_test_supported_on</dt>'
       '<dd>'
         '<ul style="style_ul;">'
-          '<li>Chrome (Windows) ...8...</li>'
+          '<li>Chrome (Windows, Mac, Linux) ...8...</li>'
         '</ul>'
       '</dd>'
       '<dt style="style_dt;">_test_supported_features</dt>'
@@ -420,12 +425,12 @@
       'type': 'string',
       'supported_on': [{
         'product': 'chrome',
-        'platforms': ['win'],
+        'platforms': ['win', 'mac'],
         'since_version': '7',
         'until_version': '',
       }],
       'features': {'dynamic_refresh': False},
-      'example_value': False
+      'example_value': 'False'
     }
     self.writer.messages['doc_since_version'] = {'text': '..$6..'}
     self.writer._AddPolicySection(self.doc_root, policy)
@@ -445,7 +450,7 @@
             '<dt style="style_dt;">_test_supported_on</dt>'
             '<dd>'
               '<ul style="style_ul;">'
-                '<li>Chrome (Windows) ..7..</li>'
+                '<li>Chrome (Windows, Mac) ..7..</li>'
               '</ul>'
             '</dd>'
             '<dt style="style_dt;">_test_supported_features</dt>'
@@ -472,6 +477,141 @@
         '</div>'
       '</root>')
 
+  def testAddPolicySectionForWindowsOnly(self):
+    policy = {
+      'name': 'PolicyName',
+      'caption': 'PolicyCaption',
+      'desc': 'PolicyDesc',
+      'type': 'int',
+      'supported_on': [{
+        'product': 'chrome',
+        'platforms': ['win'],
+        'since_version': '33',
+        'until_version': '',
+      }],
+      'features': {'dynamic_refresh': False},
+      'example_value': 123
+    }
+    self.writer.messages['doc_since_version'] = {'text': '..$6..'}
+    self.writer._AddPolicySection(self.doc_root, policy)
+    self.assertEquals(
+      self.doc_root.toxml(),
+      '<root>'
+        '<div style="margin-left: 0px">'
+          '<h3><a name="PolicyName"/>PolicyName</h3>'
+          '<span>PolicyCaption</span>'
+          '<dl>'
+            '<dt style="style_dt;">_test_data_type</dt>'
+            '<dd>Integer (REG_DWORD)</dd>'
+            '<dt style="style_dt;">_test_win_reg_loc</dt>'
+            '<dd style="style_.monospace;">MockKey\\PolicyName</dd>'
+            '<dt style="style_dt;">_test_supported_on</dt>'
+            '<dd>'
+              '<ul style="style_ul;">'
+                '<li>Chrome (Windows) ..33..</li>'
+              '</ul>'
+            '</dd>'
+            '<dt style="style_dt;">_test_supported_features</dt>'
+            '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
+            '<dt style="style_dt;">_test_description</dt>'
+            '<dd>PolicyDesc</dd>'
+            '<dt style="style_dt;">_test_example_value</dt>'
+            '<dd>0x0000007b (Windows)</dd>'
+          '</dl>'
+          '<a href="#top">_test_back_to_top</a>'
+        '</div>'
+      '</root>')
+
+  def testAddPolicySectionForMacOnly(self):
+    policy = {
+      'name': 'PolicyName',
+      'caption': 'PolicyCaption',
+      'desc': 'PolicyDesc',
+      'type': 'int',
+      'supported_on': [{
+        'product': 'chrome',
+        'platforms': ['mac'],
+        'since_version': '33',
+        'until_version': '',
+      }],
+      'features': {'dynamic_refresh': False},
+      'example_value': 123
+    }
+    self.writer.messages['doc_since_version'] = {'text': '..$6..'}
+    self.writer._AddPolicySection(self.doc_root, policy)
+    self.assertEquals(
+      self.doc_root.toxml(),
+      '<root>'
+        '<div style="margin-left: 0px">'
+          '<h3><a name="PolicyName"/>PolicyName</h3>'
+          '<span>PolicyCaption</span>'
+          '<dl>'
+            '<dt style="style_dt;">_test_data_type</dt>'
+            '<dd>Integer</dd>'
+            '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
+            '<dd style="style_.monospace;">PolicyName</dd>'
+            '<dt style="style_dt;">_test_supported_on</dt>'
+            '<dd>'
+              '<ul style="style_ul;">'
+                '<li>Chrome (Mac) ..33..</li>'
+              '</ul>'
+            '</dd>'
+            '<dt style="style_dt;">_test_supported_features</dt>'
+            '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
+            '<dt style="style_dt;">_test_description</dt>'
+            '<dd>PolicyDesc</dd>'
+            '<dt style="style_dt;">_test_example_value</dt>'
+            '<dd>123 (Mac)</dd>'
+          '</dl>'
+          '<a href="#top">_test_back_to_top</a>'
+        '</div>'
+      '</root>')
+
+  def testAddPolicySectionForLinuxOnly(self):
+    policy = {
+      'name': 'PolicyName',
+      'caption': 'PolicyCaption',
+      'desc': 'PolicyDesc',
+      'type': 'int',
+      'supported_on': [{
+        'product': 'chrome',
+        'platforms': ['linux'],
+        'since_version': '33',
+        'until_version': '',
+      }],
+      'features': {'dynamic_refresh': False},
+      'example_value': 123
+    }
+    self.writer.messages['doc_since_version'] = {'text': '..$6..'}
+    self.writer._AddPolicySection(self.doc_root, policy)
+    self.assertEquals(
+      self.doc_root.toxml(),
+      '<root>'
+        '<div style="margin-left: 0px">'
+          '<h3><a name="PolicyName"/>PolicyName</h3>'
+          '<span>PolicyCaption</span>'
+          '<dl>'
+            '<dt style="style_dt;">_test_data_type</dt>'
+            '<dd>Integer</dd>'
+            '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
+            '<dd style="style_.monospace;">PolicyName</dd>'
+            '<dt style="style_dt;">_test_supported_on</dt>'
+            '<dd>'
+              '<ul style="style_ul;">'
+                '<li>Chrome (Linux) ..33..</li>'
+              '</ul>'
+            '</dd>'
+            '<dt style="style_dt;">_test_supported_features</dt>'
+            '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
+            '<dt style="style_dt;">_test_description</dt>'
+            '<dd>PolicyDesc</dd>'
+            '<dt style="style_dt;">_test_example_value</dt>'
+            '<dd>123 (Linux)</dd>'
+          '</dl>'
+          '<a href="#top">_test_back_to_top</a>'
+        '</div>'
+      '</root>')
+
   def testAddDictionaryExample(self):
     policy = {
       'name': 'PolicyName',
@@ -480,7 +620,7 @@
       'type': 'dict',
       'supported_on': [{
         'product': 'chrome',
-        'platforms': ['win'],
+        'platforms': ['win', 'mac', 'linux'],
         'since_version': '7',
         'until_version': '',
       }],
diff --git a/grit/format/policy_templates/writers/template_writer.py b/grit/format/policy_templates/writers/template_writer.py
index 935c886..2a8b548 100644
--- a/grit/format/policy_templates/writers/template_writer.py
+++ b/grit/format/policy_templates/writers/template_writer.py
@@ -87,6 +87,17 @@
     '''Checks if the given policy can be recommended.'''
     return policy.get('features', {}).get('can_be_recommended', False)
 
+  def IsPolicySupportedOnPlatform(self, policy, platform):
+    '''Checks if |policy| is supported on |platform|.
+
+    Args:
+      policy: The dictionary of the policy.
+      platform: The platform to check; one of 'win', 'mac', 'linux' or
+        'chrome_os'.
+    '''
+    is_supported = lambda x: platform in x['platforms']
+    return any(filter(is_supported, policy['supported_on']))
+
   def _GetPoliciesForWriter(self, group):
     '''Filters the list of policies in the passed group that are supported by
     the writer.