1#!/usr/bin/env python
2# Copyright 2013 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
6import json
7from operator import itemgetter
8import unittest
9
10from extensions_paths import CHROME_EXTENSIONS
11from permissions_data_source import PermissionsDataSource
12from server_instance import ServerInstance
13from third_party.motemplate import Motemplate
14from test_file_system import TestFileSystem
15
16
17_PERMISSION_FEATURES = {
18  # This will appear for extensions with a description as defined in the
19  # permissions.json file.
20  'activeTab': {
21    'extension_types': ['extension'],
22  },
23  # This will appear for apps and extensions with an auto-generated description
24  # since the entry appears in _api_features.json.
25  'alarms': {
26    'extension_types': ['platform_app', 'extension'],
27  },
28  # This won't appear for anything since there's no entry in permissions.json
29  # and it's not an API.
30  'audioCapture': {
31    'extension_types': ['platform_app'],
32  },
33  # This won't appear for anything because it's private.
34  'commandLinePrivate': {
35    'extension_types': ['platform_app', 'extension']
36  },
37  # This will only appear for apps with an auto-generated description because
38  # it's an API.
39  'cookies': {
40    'extension_types': ['platform_app']
41  },
42  'host-permissions': {}
43}
44
45
46_PERMISSIONS_JSON = {
47  # This will appear for both apps and extensions with a custom description,
48  # anchor, etc.
49  'host-permissions': {
50    'anchor': 'custom-anchor',
51    'extension_types': ['platform_app', 'extension'],
52    'literal_name': True,
53    'name': 'match pattern',
54    'partial': 'permissions/host_permissions.html',
55  },
56  # A custom 'partial' here overrides the default partial.
57  'activeTab': {
58    'partial': 'permissions/active_tab.html'
59  },
60}
61
62
63_PERMISSIONS_PARTIALS = {
64  'active_tab.html': 'active tab',
65  'host_permissions.html': 'host permissions',
66  'generic_description.html': 'generic description',
67}
68
69
70_API_FEATURES = {
71  'alarms': {
72    'dependencies': ['permission:alarms']
73  },
74  'cookies': {
75    'dependencies': ['permission:cookies']
76  },
77}
78
79
80class PermissionsDataSourceTest(unittest.TestCase):
81  def testCreatePermissionsDataSource(self):
82    expected_extensions = [
83      {
84        'anchor': 'custom-anchor',
85        'description': 'host permissions',
86        'extension_types': ['platform_app', 'extension'],
87        'literal_name': True,
88        'name': 'match pattern',
89        'channel': 'stable'
90      },
91      {
92        'anchor': 'activeTab',
93        'description': 'active tab',
94        'extension_types': ['extension'],
95        'name': 'activeTab',
96        'channel': 'stable'
97      },
98      {
99        'anchor': 'alarms',
100        'description': 'generic description',
101        'extension_types': ['platform_app', 'extension'],
102        'name': 'alarms',
103        'channel': 'stable'
104      },
105    ]
106
107    expected_apps = [
108      {
109        'anchor': 'custom-anchor',
110        'description': 'host permissions',
111        'extension_types': ['platform_app', 'extension'],
112        'literal_name': True,
113        'name': 'match pattern',
114        'channel': 'stable'
115      },
116      {
117        'anchor': 'alarms',
118        'description': 'generic description',
119        'extension_types': ['platform_app', 'extension'],
120        'name': 'alarms',
121        'channel': 'stable'
122      },
123      {
124        'anchor': 'cookies',
125        'description': 'generic description',
126        'extension_types': ['platform_app'],
127        'name': 'cookies',
128        'channel': 'stable'
129      },
130    ]
131
132    test_file_system = TestFileSystem({
133      'api': {
134        '_api_features.json': json.dumps(_API_FEATURES),
135        '_manifest_features.json': '{}',
136        '_permission_features.json': json.dumps(_PERMISSION_FEATURES),
137      },
138      'docs': {
139        'templates': {
140          'json': {
141            'manifest.json': '{}',
142            'permissions.json': json.dumps(_PERMISSIONS_JSON),
143          },
144          'private': {
145            'permissions': _PERMISSIONS_PARTIALS
146          },
147        }
148      }
149    }, relative_to=CHROME_EXTENSIONS)
150
151    permissions_data_source = PermissionsDataSource(
152        ServerInstance.ForTest(test_file_system), None)
153
154    actual_extensions = permissions_data_source.get('declare_extensions')
155    actual_apps = permissions_data_source.get('declare_apps')
156
157    # Normalise all test data.
158    #   - Sort keys. Since the tests don't use OrderedDicts we can't make
159    #     assertions about the order, which is unfortunate. Oh well.
160    #   - Render all of the Handlerbar instances so that we can use ==.
161    #     Motemplates don't implement __eq__, but they probably should.
162    for lst in (actual_apps, actual_extensions,
163                expected_apps, expected_extensions):
164      lst.sort(key=itemgetter('name'))
165      for mapping in lst:
166        for key, value in mapping.iteritems():
167          if isinstance(value, Motemplate):
168            mapping[key] = value.Render().text
169
170    self.assertEqual(expected_extensions, actual_extensions)
171    self.assertEqual(expected_apps, actual_apps)
172
173
174if __name__ == '__main__':
175  unittest.main()
176