Merge from Chromium at DEPS revision 267aeeb8d85c

This commit was generated by merge_to_master.py.

Change-Id: If25117d42e5d25a7d668afba62840d41caa60320
diff --git a/grit/format/policy_templates/writer_configuration.py b/grit/format/policy_templates/writer_configuration.py
index 00da0cc..88de6b5 100644
--- a/grit/format/policy_templates/writer_configuration.py
+++ b/grit/format/policy_templates/writer_configuration.py
@@ -33,6 +33,7 @@
       'win_recommended_category_path': ['chromium_recommended'],
       'admx_namespace': 'Chromium.Policies.Chromium',
       'admx_prefix': 'chromium',
+      'linux_policy_path': '/etc/chromium/policies/',
     }
   elif '_google_chrome' in defines:
     config = {
@@ -47,6 +48,7 @@
       'win_recommended_category_path': ['google', 'googlechrome_recommended'],
       'admx_namespace': 'Google.Policies.Chrome',
       'admx_prefix': 'chrome',
+      'linux_policy_path': '/etc/opt/chrome/policies/',
     }
   else:
     raise Exception('Unknown build')
diff --git a/grit/format/policy_templates/writers/adm_writer.py b/grit/format/policy_templates/writers/adm_writer.py
index 6a2f8b2..bffbeb5 100644
--- a/grit/format/policy_templates/writers/adm_writer.py
+++ b/grit/format/policy_templates/writers/adm_writer.py
@@ -153,9 +153,10 @@
     builder.AddLine()
 
   def WritePolicy(self, policy):
-    self._WritePolicy(policy,
-                      self.config['win_reg_mandatory_key_name'],
-                      self.policies)
+    if self.CanBeMandatory(policy):
+      self._WritePolicy(policy,
+                        self.config['win_reg_mandatory_key_name'],
+                        self.policies)
 
   def WriteRecommendedPolicy(self, policy):
     self._WritePolicy(policy,
diff --git a/grit/format/policy_templates/writers/adm_writer_unittest.py b/grit/format/policy_templates/writers/adm_writer_unittest.py
index 52e4aee..82374bb 100644
--- a/grit/format/policy_templates/writers/adm_writer_unittest.py
+++ b/grit/format/policy_templates/writers/adm_writer_unittest.py
@@ -147,6 +147,70 @@
 MainPolicy_Explain="Description of main."''')
     self.CompareOutputs(output, expected_output)
 
+  def testMainPolicyRecommendedOnly(self):
+    # Tests a policy group with a single policy of type 'main'.
+    grd = self.PrepareTest('''
+      {
+        'policy_definitions': [
+          {
+            'name': 'MainPolicy',
+            'type': 'main',
+            'supported_on': ['chrome.win:8-'],
+            'features': {
+              'can_be_recommended': True,
+              'can_be_mandatory': False
+            },
+            'caption': 'Caption of main.',
+            'desc': 'Description of main.',
+          },
+        ],
+        'placeholders': [],
+        'messages': {
+          'win_supported_winxpsp2': {
+            'text': 'At least Windows 3.12', 'desc': 'blah'
+          },
+          'doc_recommended': {
+            'text': 'Recommended', 'desc': 'bleh'
+          }
+        }
+      }''')
+    output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'adm', 'en')
+    expected_output = self.ConstructOutput(
+        ['MACHINE', 'USER'], '''
+  CATEGORY !!google
+    CATEGORY !!googlechrome
+      KEYNAME "Software\\Policies\\Google\\Chrome"
+
+    END CATEGORY
+  END CATEGORY
+
+  CATEGORY !!google
+    CATEGORY !!googlechrome_recommended
+      KEYNAME "Software\\Policies\\Google\\Chrome\\Recommended"
+
+      POLICY !!MainPolicy_Policy
+        #if version >= 4
+          SUPPORTED !!SUPPORTED_WINXPSP2
+        #endif
+        EXPLAIN !!MainPolicy_Explain
+        VALUENAME "MainPolicy"
+        VALUEON NUMERIC 1
+        VALUEOFF NUMERIC 0
+      END POLICY
+
+    END CATEGORY
+  END CATEGORY
+
+
+''', '''[Strings]
+SUPPORTED_WINXPSP2="At least Windows 3.12"
+google="Google"
+googlechrome="Google Chrome"
+googlechrome_recommended="Google Chrome - Recommended"
+MainPolicy_Policy="Caption of main."
+MainPolicy_Explain="Description of main."''')
+    self.CompareOutputs(output, expected_output)
+
   def testStringPolicy(self):
     # Tests a policy group with a single policy of type 'string'.
     grd = self.PrepareTest('''
diff --git a/grit/format/policy_templates/writers/admx_writer.py b/grit/format/policy_templates/writers/admx_writer.py
index bc33c19..0d4394b 100644
--- a/grit/format/policy_templates/writers/admx_writer.py
+++ b/grit/format/policy_templates/writers/admx_writer.py
@@ -295,10 +295,11 @@
       raise Exception('Unknown policy type %s.' % policy_type)
 
   def WritePolicy(self, policy):
-    self._WritePolicy(policy,
-                      policy['name'],
-                      self.config['win_reg_mandatory_key_name'],
-                      self._active_mandatory_policy_group_name)
+    if self.CanBeMandatory(policy):
+      self._WritePolicy(policy,
+                        policy['name'],
+                        self.config['win_reg_mandatory_key_name'],
+                        self._active_mandatory_policy_group_name)
 
   def WriteRecommendedPolicy(self, policy):
     self._WritePolicy(policy,
diff --git a/grit/format/policy_templates/writers/admx_writer_unittest.py b/grit/format/policy_templates/writers/admx_writer_unittest.py
index a573f26..cb3d39e 100644
--- a/grit/format/policy_templates/writers/admx_writer_unittest.py
+++ b/grit/format/policy_templates/writers/admx_writer_unittest.py
@@ -219,6 +219,46 @@
 
     self.AssertXMLEquals(output, expected_output)
 
+  def testRecommendedOnlyPolicy(self):
+    main_policy = {
+      'name': 'DummyMainPolicy',
+      'type': 'main',
+      'features': {
+        'can_be_recommended': True,
+        'can_be_mandatory': False,
+      }
+    }
+
+    policy_group = {
+      'name': 'PolicyGroup',
+      'policies': [main_policy],
+    }
+    self.writer.BeginTemplate()
+    self.writer.BeginRecommendedPolicyGroup(policy_group)
+
+    self.writer.WritePolicy(main_policy)
+    self.writer.WriteRecommendedPolicy(main_policy)
+
+    output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
+    expected_output = (
+        '<policy class="TestClass" displayName="$(string.DummyMainPolicy)"'
+        ' explainText="$(string.DummyMainPolicy_Explain)"'
+        ' key="Software\\Policies\\Test\\Recommended"'
+        ' name="DummyMainPolicy_recommended"'
+        ' presentation="$(presentation.DummyMainPolicy)"'
+        ' valueName="DummyMainPolicy">\n'
+        '  <parentCategory ref="PolicyGroup_recommended"/>\n'
+        '  <supportedOn ref="SUPPORTED_TESTOS"/>\n'
+        '  <enabledValue>\n'
+        '    <decimal value="1"/>\n'
+        '  </enabledValue>\n'
+        '  <disabledValue>\n'
+        '    <decimal value="0"/>\n'
+        '  </disabledValue>\n'
+        '</policy>')
+
+    self.AssertXMLEquals(output, expected_output)
+
   def testStringPolicy(self):
     string_policy = {
       'name': 'SampleStringPolicy',
diff --git a/grit/format/policy_templates/writers/doc_writer.py b/grit/format/policy_templates/writers/doc_writer.py
index e8543c2..d8f108d 100644
--- a/grit/format/policy_templates/writers/doc_writer.py
+++ b/grit/format/policy_templates/writers/doc_writer.py
@@ -4,6 +4,7 @@
 # found in the LICENSE file.
 
 
+import json
 from xml.dom import minidom
 from grit import lazy_re
 from grit.format.policy_templates.writers import xml_formatted_writer
@@ -179,7 +180,10 @@
     win = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre'])
     win_text = []
     cnt = 1
-    key_name = self.config['win_reg_mandatory_key_name']
+    if self.CanBeRecommended(policy) and not self.CanBeMandatory(policy):
+      key_name = self.config['win_reg_recommended_key_name']
+    else:
+      key_name = self.config['win_reg_mandatory_key_name']
     for item in example_value:
       win_text.append(
           '%s\\%s\\%d = "%s"' %
@@ -286,9 +290,12 @@
     '''
     self.AddElement(parent, 'dt', {}, 'Windows:')
     win = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre'])
-    key_name = self.config['win_reg_mandatory_key_name']
-    example = str(policy['example_value'])
-    self.AddText(win, '%s\\%s = "%s"' % (key_name, policy['name'], example))
+    if self.CanBeRecommended(policy) and not self.CanBeMandatory(policy):
+      key_name = self.config['win_reg_recommended_key_name']
+    else:
+      key_name = self.config['win_reg_mandatory_key_name']
+    example = json.dumps(policy['example_value'])
+    self.AddText(win, '%s\\%s = %s' % (key_name, policy['name'], example))
 
   def _AddDictionaryExampleLinux(self, parent, policy):
     '''Adds an example value for Linux of a 'dict' policy to a DOM node.
@@ -300,7 +307,7 @@
     '''
     self.AddElement(parent, 'dt', {}, 'Linux:')
     linux = self._AddStyledElement(parent, 'dd', ['.monospace'])
-    example = str(policy['example_value'])
+    example = json.dumps(policy['example_value'])
     self.AddText(linux, '%s: %s' % (policy['name'], example))
 
   def _AddDictionaryExample(self, parent, policy):
@@ -458,10 +465,14 @@
     if policy['type'] != 'external':
       # All types except 'external' can be set through platform policy.
       if self.IsPolicySupportedOnPlatform(policy, 'win'):
+        if self.CanBeRecommended(policy) and not self.CanBeMandatory(policy):
+          key_name = self.config['win_reg_recommended_key_name']
+        else:
+          key_name = self.config['win_reg_mandatory_key_name']
         self._AddPolicyAttribute(
             dl,
             'win_reg_loc',
-            self.config['win_reg_mandatory_key_name'] + '\\' + policy['name'],
+            key_name + '\\' + policy['name'],
             ['.monospace'])
       if (self.IsPolicySupportedOnPlatform(policy, 'linux') or
           self.IsPolicySupportedOnPlatform(policy, 'mac')):
@@ -644,13 +655,15 @@
       'dict': 'Dictionary',
       'external': 'External data reference',
     }
+    reg_dict = 'REG_SZ; %s' % self._GetLocalizedMessage(
+        'complex_policies_on_windows')
     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',
+      'dict': reg_dict,
     }
     # 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 05ea240..15d8b85 100644
--- a/grit/format/policy_templates/writers/doc_writer_unittest.py
+++ b/grit/format/policy_templates/writers/doc_writer_unittest.py
@@ -6,6 +6,7 @@
 '''Unit tests for grit.format.policy_templates.writers.doc_writer'''
 
 
+import json
 import os
 import sys
 if __name__ == '__main__':
@@ -37,9 +38,11 @@
         'frame_name': 'Chrome Frame',
         'os_name': 'Chrome OS',
         'win_reg_mandatory_key_name': 'MockKey',
+        'win_reg_recommended_key_name': 'MockKeyRec',
       })
     self.writer.messages = {
       'doc_back_to_top': {'text': '_test_back_to_top'},
+      'doc_complex_policies_on_windows': {'text': '_test_complex_policies_win'},
       'doc_data_type': {'text': '_test_data_type'},
       'doc_description': {'text': '_test_description'},
       'doc_description_column_title': {
@@ -48,6 +51,7 @@
       'doc_example_value': {'text': '_test_example_value'},
       'doc_feature_dynamic_refresh': {'text': '_test_feature_dynamic_refresh'},
       'doc_feature_can_be_recommended': {'text': '_test_feature_recommended'},
+      'doc_feature_can_be_mandatory': {'text': '_test_feature_mandatory'},
       'doc_intro': {'text': '_test_intro'},
       'doc_mac_linux_pref_name': {'text': '_test_mac_linux_pref_name'},
       'doc_note': {'text': '_test_note'},
@@ -414,6 +418,117 @@
         '<dd>0x00000000 (Windows), false (Linux), &lt;false /&gt; (Mac)</dd>'
       '</dl></root>')
 
+  def testAddDictPolicyDetails(self):
+    # Test if the definition list (<dl>) of policy details is created correctly
+    # for 'dict' policies.
+    policy = {
+      'type': 'dict',
+      'name': 'TestPolicyName',
+      'caption': 'TestPolicyCaption',
+      'desc': 'TestPolicyDesc',
+      'supported_on': [{
+        'product': 'chrome',
+        'platforms': ['win', 'mac', 'linux'],
+        'since_version': '8',
+        'until_version': '',
+      }],
+      'features': {'dynamic_refresh': False},
+      'example_value': { 'foo': 123 }
+    }
+    self.writer.messages['doc_since_version'] = {'text': '...$6...'}
+    self.writer._AddPolicyDetails(self.doc_root, policy)
+    self.assertEquals(
+      self.doc_root.toxml(),
+      '<root><dl>'
+      '<dt style="style_dt;">_test_data_type</dt><dd>Dictionary (REG_SZ; _test_complex_policies_win)</dd>'
+      '<dt style="style_dt;">_test_win_reg_loc</dt>'
+      '<dd style="style_.monospace;">MockKey\TestPolicyName</dd>'
+      '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
+        '<dd style="style_.monospace;">TestPolicyName</dd>'
+      '<dt style="style_dt;">_test_supported_on</dt>'
+      '<dd>'
+        '<ul style="style_ul;">'
+          '<li>Chrome (Windows, Mac, Linux) ...8...</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>TestPolicyDesc</dd>'
+      '<dt style="style_dt;">_test_example_value</dt>'
+        '<dd>'
+          '<dl style="style_dd dl;">'
+            '<dt>Windows:</dt>'
+            '<dd style="style_.monospace;style_.pre;">MockKey\TestPolicyName = {&quot;foo&quot;: 123}</dd>'
+            '<dt>Linux:</dt>'
+            '<dd style="style_.monospace;">TestPolicyName: {&quot;foo&quot;: 123}</dd>'
+            '<dt>Mac:</dt>'
+            '<dd style="style_.monospace;style_.pre;">'
+              '&lt;key&gt;TestPolicyName&lt;/key&gt;\n'
+              '&lt;dict&gt;\n'
+              '  &lt;key&gt;foo&lt;/key&gt;\n'
+              '  &lt;integer&gt;123&lt;/integer&gt;\n'
+              '&lt;/dict&gt;'
+            '</dd>'
+          '</dl>'
+        '</dd>'
+      '</dl></root>')
+
+  def testAddPolicyDetailsRecommendedOnly(self):
+    policy = {
+      'type': 'main',
+      'name': 'TestPolicyName',
+      'caption': 'TestPolicyCaption',
+      'desc': 'TestPolicyDesc',
+      'supported_on': [{
+        'product': 'chrome',
+        'platforms': ['win', 'mac', 'linux'],
+        'since_version': '8',
+        'until_version': '',
+      }, {
+        'product': 'chrome',
+        'platforms': ['android'],
+        'since_version': '30',
+        'until_version': '',
+      }, {
+        'product': 'chrome',
+        'platforms': ['ios'],
+        'since_version': '34',
+        'until_version': '',
+      }],
+      'features': {
+        'dynamic_refresh': False,
+        'can_be_mandatory': False,
+        'can_be_recommended': True
+      },
+      'example_value': False
+    }
+    self.writer.messages['doc_since_version'] = {'text': '...$6...'}
+    self.writer._AddPolicyDetails(self.doc_root, policy)
+    self.assertEquals(
+      self.doc_root.toxml(),
+      '<root><dl>'
+      '<dt style="style_dt;">_test_data_type</dt><dd>Boolean (REG_DWORD)</dd>'
+      '<dt style="style_dt;">_test_win_reg_loc</dt>'
+      '<dd style="style_.monospace;">MockKeyRec\TestPolicyName</dd>'
+      '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
+        '<dd style="style_.monospace;">TestPolicyName</dd>'
+      '<dt style="style_dt;">_test_supported_on</dt>'
+      '<dd>'
+        '<ul style="style_ul;">'
+          '<li>Chrome (Windows, Mac, Linux) ...8...</li>'
+          '<li>Chrome (Android) ...30...</li>'
+          '<li>Chrome (iOS) ...34...</li>'
+        '</ul>'
+      '</dd>'
+      '<dt style="style_dt;">_test_supported_features</dt>'
+        '<dd>_test_feature_mandatory: _test_not_supported,'
+        ' _test_feature_recommended: _test_supported,'
+        ' _test_feature_dynamic_refresh: _test_not_supported</dd>'
+      '<dt style="style_dt;">_test_description</dt><dd>TestPolicyDesc</dd>'
+      '<dt style="style_dt;">_test_example_value</dt>'
+        '<dd>0x00000000 (Windows), false (Linux), &lt;false /&gt; (Mac)</dd>'
+      '</dl></root>')
+
   def testAddPolicyNote(self):
     # TODO(jkummerow): The functionality tested by this test is currently not
     # used for anything and will probably soon be removed.
@@ -688,14 +803,14 @@
       },
     }
     self.writer._AddDictionaryExample(self.doc_root, policy)
-    value = str(policy['example_value'])
+    value = json.dumps(policy['example_value']).replace('"', '&quot;')
     self.assertEquals(
       self.doc_root.toxml(),
       '<root>'
         '<dl style="style_dd dl;">'
           '<dt>Windows:</dt>'
           '<dd style="style_.monospace;style_.pre;">MockKey\PolicyName = '
-              '&quot;' + value + '&quot;'
+              + value +
           '</dd>'
           '<dt>Linux:</dt>'
           '<dd style="style_.monospace;">PolicyName: ' + value + '</dd>'
diff --git a/grit/format/policy_templates/writers/json_writer.py b/grit/format/policy_templates/writers/json_writer.py
index 673bbf7..f5af8c1 100644
--- a/grit/format/policy_templates/writers/json_writer.py
+++ b/grit/format/policy_templates/writers/json_writer.py
@@ -49,6 +49,13 @@
     if not self._first_written:
       self._out[-2] += ','
 
+    if not self.CanBeMandatory(policy) and self.CanBeRecommended(policy):
+      line = '  // Note: this policy is supported only in recommended mode.'
+      self._out.append(line)
+      line = '  // The JSON file should be placed in %srecommended.' % \
+             self.config['linux_policy_path']
+      self._out.append(line)
+
     line = '  // %s' % policy['caption']
     self._out.append(line)
     self._out.append(HEADER_DELIMETER)
diff --git a/grit/format/policy_templates/writers/json_writer_unittest.py b/grit/format/policy_templates/writers/json_writer_unittest.py
index 05ae255..b2ed1ef 100644
--- a/grit/format/policy_templates/writers/json_writer_unittest.py
+++ b/grit/format/policy_templates/writers/json_writer_unittest.py
@@ -86,6 +86,40 @@
         '}')
     self.CompareOutputs(output, expected_output)
 
+  def testRecommendedOnlyPolicy(self):
+    # Tests a policy group with a single policy of type 'main'.
+    grd = self.PrepareTest(
+        '{'
+        '  "policy_definitions": ['
+        '    {'
+        '      "name": "MainPolicy",'
+        '      "type": "main",'
+        '      "caption": "Example Main Policy",'
+        '      "desc": "Example Main Policy",'
+        '      "features": {'
+        '        "can_be_recommended": True,'
+        '        "can_be_mandatory": False'
+        '      },'
+        '      "supported_on": ["chrome.linux:8-"],'
+        '      "example_value": True'
+        '    },'
+        '  ],'
+        '  "placeholders": [],'
+        '  "messages": {},'
+        '}')
+    output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'json', 'en')
+    expected_output = (
+        TEMPLATE_HEADER +
+        '  // Note: this policy is supported only in recommended mode.\n' +
+        '  // The JSON file should be placed in' +
+        ' /etc/opt/chrome/policies/recommended.\n' +
+        '  // Example Main Policy\n' +
+        HEADER_DELIMETER +
+        '  // Example Main Policy\n\n'
+        '  //"MainPolicy": true\n\n'
+        '}')
+    self.CompareOutputs(output, expected_output)
+
   def testStringPolicy(self):
     # Tests a policy group with a single policy of type 'string'.
     grd = self.PrepareTest(
diff --git a/grit/format/policy_templates/writers/plist_writer.py b/grit/format/policy_templates/writers/plist_writer.py
index 6ca905b..6d929d6 100644
--- a/grit/format/policy_templates/writers/plist_writer.py
+++ b/grit/format/policy_templates/writers/plist_writer.py
@@ -67,7 +67,7 @@
     self.AddElement(parent, 'key', {}, key_string)
     self.AddElement(parent, 'string', {}, value_string)
 
-  def _AddTargets(self, parent):
+  def _AddTargets(self, parent, policy):
     '''Adds the following XML snippet to an XML element:
       <key>pfm_targets</key>
       <array>
@@ -78,7 +78,10 @@
         parent: The parent XML element where the snippet will be added.
     '''
     array = self._AddKeyValuePair(parent, 'pfm_targets', 'array')
-    self.AddElement(array, 'string', {}, 'user-managed')
+    if self.CanBeRecommended(policy):
+      self.AddElement(array, 'string', {}, 'user')
+    if self.CanBeMandatory(policy):
+      self.AddElement(array, 'string', {}, 'user-managed')
 
   def PreprocessPolicies(self, policy_list):
     return self.FlattenGroupsAndSortPolicies(policy_list)
@@ -97,7 +100,7 @@
     # Those files are generated by plist_strings_writer.
     self._AddStringKeyValuePair(dict, 'pfm_description', '')
     self._AddStringKeyValuePair(dict, 'pfm_title', '')
-    self._AddTargets(dict)
+    self._AddTargets(dict, policy)
     self._AddStringKeyValuePair(dict, 'pfm_type',
                                 self.TYPE_TO_INPUT[policy_type])
     if policy_type in ('int-enum', 'string-enum'):
diff --git a/grit/format/policy_templates/writers/plist_writer_unittest.py b/grit/format/policy_templates/writers/plist_writer_unittest.py
index f76db73..ddbdbfe 100644
--- a/grit/format/policy_templates/writers/plist_writer_unittest.py
+++ b/grit/format/policy_templates/writers/plist_writer_unittest.py
@@ -118,6 +118,108 @@
     </array>''')
     self.assertEquals(output.strip(), expected_output.strip())
 
+  def testRecommendedPolicy(self):
+    # Tests a policy group with a single policy of type 'main'.
+    grd = self.PrepareTest('''
+      {
+        'policy_definitions': [
+          {
+            'name': 'MainGroup',
+            'type': 'group',
+            'policies': [{
+              'name': 'MainPolicy',
+              'type': 'main',
+              'desc': '',
+              'caption': '',
+              'features': {
+                'can_be_recommended' : True
+              },
+              'supported_on': ['chrome.mac:8-'],
+            }],
+            'desc': '',
+            'caption': '',
+          },
+        ],
+        'placeholders': [],
+        'messages': {}
+      }''')
+    output = self.GetOutput(
+        grd,
+        'fr',
+        {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
+        'plist',
+        'en')
+    expected_output = self._GetExpectedOutputs(
+        'Chromium', 'com.example.Test', '''<array>
+      <dict>
+        <key>pfm_name</key>
+        <string>MainPolicy</string>
+        <key>pfm_description</key>
+        <string/>
+        <key>pfm_title</key>
+        <string/>
+        <key>pfm_targets</key>
+        <array>
+          <string>user</string>
+          <string>user-managed</string>
+        </array>
+        <key>pfm_type</key>
+        <string>boolean</string>
+      </dict>
+    </array>''')
+    self.assertEquals(output.strip(), expected_output.strip())
+
+  def testRecommendedOnlyPolicy(self):
+    # Tests a policy group with a single policy of type 'main'.
+    grd = self.PrepareTest('''
+      {
+        'policy_definitions': [
+          {
+            'name': 'MainGroup',
+            'type': 'group',
+            'policies': [{
+              'name': 'MainPolicy',
+              'type': 'main',
+              'desc': '',
+              'caption': '',
+              'features': {
+                'can_be_recommended' : True,
+                'can_be_mandatory' : False
+              },
+              'supported_on': ['chrome.mac:8-'],
+            }],
+            'desc': '',
+            'caption': '',
+          },
+        ],
+        'placeholders': [],
+        'messages': {}
+      }''')
+    output = self.GetOutput(
+        grd,
+        'fr',
+        {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
+        'plist',
+        'en')
+    expected_output = self._GetExpectedOutputs(
+        'Chromium', 'com.example.Test', '''<array>
+      <dict>
+        <key>pfm_name</key>
+        <string>MainPolicy</string>
+        <key>pfm_description</key>
+        <string/>
+        <key>pfm_title</key>
+        <string/>
+        <key>pfm_targets</key>
+        <array>
+          <string>user</string>
+        </array>
+        <key>pfm_type</key>
+        <string>boolean</string>
+      </dict>
+    </array>''')
+    self.assertEquals(output.strip(), expected_output.strip())
+
   def testStringPolicy(self):
     # Tests a policy group with a single policy of type 'string'.
     grd = self.PrepareTest('''
diff --git a/grit/format/policy_templates/writers/reg_writer.py b/grit/format/policy_templates/writers/reg_writer.py
index dcb70f4..ad83046 100644
--- a/grit/format/policy_templates/writers/reg_writer.py
+++ b/grit/format/policy_templates/writers/reg_writer.py
@@ -83,9 +83,10 @@
       list.append('"%s"=%s' % (policy['name'], example_value_str))
 
   def WritePolicy(self, policy):
-    self._WritePolicy(policy,
-                      self.config['win_reg_mandatory_key_name'],
-                      self._mandatory)
+    if self.CanBeMandatory(policy):
+      self._WritePolicy(policy,
+                        self.config['win_reg_mandatory_key_name'],
+                        self._mandatory)
 
   def WriteRecommendedPolicy(self, policy):
     self._WritePolicy(policy,
diff --git a/grit/format/policy_templates/writers/reg_writer_unittest.py b/grit/format/policy_templates/writers/reg_writer_unittest.py
index f698cb4..88fb2e2 100644
--- a/grit/format/policy_templates/writers/reg_writer_unittest.py
+++ b/grit/format/policy_templates/writers/reg_writer_unittest.py
@@ -77,6 +77,35 @@
         '"MainPolicy"=dword:00000001'])
     self.CompareOutputs(output, expected_output)
 
+  def testRecommendedMainPolicy(self):
+    # Tests a policy group with a single policy of type 'main'.
+    grd = self.PrepareTest(
+        '{'
+        '  "policy_definitions": ['
+        '    {'
+        '      "name": "MainPolicy",'
+        '      "type": "main",'
+        '      "features": {'
+        '        "can_be_recommended": True,'
+        '        "can_be_mandatory": False '
+        '      },'
+        '      "caption": "",'
+        '      "desc": "",'
+        '      "supported_on": ["chrome.win:8-"],'
+        '      "example_value": True'
+        '    },'
+        '  ],'
+        '  "placeholders": [],'
+        '  "messages": {},'
+        '}')
+    output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'reg', 'en')
+    expected_output = self.NEWLINE.join([
+        'Windows Registry Editor Version 5.00',
+        '',
+        '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Google\\Chrome\\Recommended]',
+        '"MainPolicy"=dword:00000001'])
+    self.CompareOutputs(output, expected_output)
+
   def testStringPolicy(self):
     # Tests a policy group with a single policy of type 'string'.
     grd = self.PrepareTest(
diff --git a/grit/format/policy_templates/writers/template_writer.py b/grit/format/policy_templates/writers/template_writer.py
index 2a8b548..bd48425 100644
--- a/grit/format/policy_templates/writers/template_writer.py
+++ b/grit/format/policy_templates/writers/template_writer.py
@@ -87,6 +87,10 @@
     '''Checks if the given policy can be recommended.'''
     return policy.get('features', {}).get('can_be_recommended', False)
 
+  def CanBeMandatory(self, policy):
+    '''Checks if the given policy can be mandatory.'''
+    return policy.get('features', {}).get('can_be_mandatory', True)
+
   def IsPolicySupportedOnPlatform(self, policy, platform):
     '''Checks if |policy| is supported on |platform|.
 
diff --git a/grit/format/resource_map_unittest.py b/grit/format/resource_map_unittest.py
index cc6a79b..55de504 100644
--- a/grit/format/resource_map_unittest.py
+++ b/grit/format/resource_map_unittest.py
@@ -94,7 +94,7 @@
 };
 const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output)
 
-  def testFormatResourceMapOutputAllEqualsFalse(self):
+  def testFormatResourceMapWithOutputAllEqualsFalseForStructures(self):
     grd = grd_reader.Parse(StringIO.StringIO(
       '''<?xml version="1.0" encoding="UTF-8"?>
       <grit latest_public_release="2" source_lang_id="en" current_release="3"
@@ -153,6 +153,70 @@
 };
 const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output)
 
+  def testFormatResourceMapWithOutputAllEqualsFalseForIncludes(self):
+    grd = grd_reader.Parse(StringIO.StringIO(
+      '''<?xml version="1.0" encoding="UTF-8"?>
+      <grit latest_public_release="2" source_lang_id="en" current_release="3"
+            base_dir="." output_all_resource_defines="false">
+        <outputs>
+          <output type="rc_header" filename="the_rc_header.h" />
+          <output type="resource_map_header"
+                  filename="the_resource_map_header.h" />
+        </outputs>
+        <release seq="3">
+          <structures first_id="300">
+            <structure type="menu" name="IDC_KLONKMENU"
+                       file="grit\\testdata\\klonk.rc" encoding="utf-16" />
+          </structures>
+          <includes first_id="10000">
+            <include type="foo" file="abc" name="IDS_FIRSTPRESENT" />
+            <if expr="False">
+              <include type="foo" file="def" name="IDS_MISSING" />
+            </if>
+            <include type="foo" file="mno" name="IDS_THIRDPRESENT" />
+         </includes>
+        </release>
+      </grit>'''), util.PathFromRoot('.'))
+    grd.SetOutputLanguage('en')
+    grd.RunGatherers()
+    output = util.StripBlankLinesAndComments(''.join(
+        resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
+    self.assertEqual('''\
+#include <stddef.h>
+#ifndef GRIT_RESOURCE_MAP_STRUCT_
+#define GRIT_RESOURCE_MAP_STRUCT_
+struct GritResourceMap {
+  const char* const name;
+  int value;
+};
+#endif // GRIT_RESOURCE_MAP_STRUCT_
+extern const GritResourceMap kTheRcHeader[];
+extern const size_t kTheRcHeaderSize;''', output)
+    output = util.StripBlankLinesAndComments(''.join(
+        resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
+    self.assertEqual('''\
+#include "the_resource_map_header.h"
+#include "base/basictypes.h"
+#include "the_rc_header.h"
+const GritResourceMap kTheRcHeader[] = {
+  {"IDC_KLONKMENU", IDC_KLONKMENU},
+  {"IDS_FIRSTPRESENT", IDS_FIRSTPRESENT},
+  {"IDS_THIRDPRESENT", IDS_THIRDPRESENT},
+};
+const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output)
+    output = util.StripBlankLinesAndComments(''.join(
+        resource_map.GetFormatter('resource_file_map_source')(grd, 'en', '.')))
+    self.assertEqual('''\
+#include "the_resource_map_header.h"
+#include "base/basictypes.h"
+#include "the_rc_header.h"
+const GritResourceMap kTheRcHeader[] = {
+  {"grit/testdata/klonk.rc", IDC_KLONKMENU},
+  {"abc", IDS_FIRSTPRESENT},
+  {"mno", IDS_THIRDPRESENT},
+};
+const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output)
+
   def testFormatStringResourceMap(self):
     grd = grd_reader.Parse(StringIO.StringIO(
       '''<?xml version="1.0" encoding="UTF-8"?>
diff --git a/grit/node/include.py b/grit/node/include.py
index 0f114c3..8d32064 100644
--- a/grit/node/include.py
+++ b/grit/node/include.py
@@ -119,7 +119,9 @@
   def GeneratesResourceMapEntry(self, output_all_resource_defines,
                                 is_active_descendant):
     # includes always generate resource entries.
-    return True
+    if output_all_resource_defines:
+      return True
+    return is_active_descendant
 
   @staticmethod
   def Construct(parent, name, type, file, translateable=True,