Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(651)

Side by Side Diff: chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc

Issue 594003002: Added unit tests for ChromePermissionMessageProvider (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/chrome_tests_unit.gypi ('k') | extensions/common/test_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/common/extensions/permissions/chrome_permission_message_provide r.h"
6
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_service_test_base.h"
11 #include "chrome/browser/extensions/permissions_updater.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/grit/generated_resources.h"
14 #include "components/crx_file/id_util.h"
15 #include "extensions/browser/extension_prefs.h"
16 #include "extensions/browser/extension_registry.h"
17 #include "extensions/common/extension_builder.h"
18 #include "extensions/common/manifest.h"
19 #include "extensions/common/manifest_handlers/permissions_parser.h"
20 #include "extensions/common/permissions/permissions_data.h"
21 #include "extensions/common/test_util.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/base/l10n/l10n_util.h"
sashab 2014/09/23 04:52:56 Some of these #includes violate checkdeps rules:
scheib 2014/09/23 17:10:54 Looking into this raises a few questions: 1. Shou
sashab 2014/09/24 23:23:49 I'm actually really glad you brought this up - it
24
25 namespace extensions {
26
27 // Tests that ChromePermissionMessageProvider provides not only correct, but
28 // meaningful permission messages.
29 // There are two main types of permission messages generated that we need to
30 // test:
31 // 1. The full set of required permissions, displayed at install time (or when
32 // the app has been disabled automatically and needs to be re-enabled)
33 // 2. The various combinations of optional permissions, displayed in a prompt
34 // when confirming the permission during runtime
35 // 3. The split set of required/optional permissions, as displayed in the App
36 // Info dialog, where the optional permissions are individually revokable.
37 // Some of these tests are currently 'anti-tests' - they demonstrate existing
scheib 2014/09/23 17:10:54 Which ones? Can I search this file for TODO or 'An
sashab 2014/09/24 23:23:49 Preceded them with 'AntiTest_'.
38 // problematic functionality. These tests will be changed as the correct
39 // behaviour is implemented.
40 class ChromePermissionMessageProviderUnittest
41 : public ExtensionServiceTestBase {
42 public:
43 ChromePermissionMessageProviderUnittest()
44 : message_provider_(new ChromePermissionMessageProvider()) {}
45 virtual ~ChromePermissionMessageProviderUnittest() {}
46
47 // Overridden from testing::Test:
48 virtual void SetUp() OVERRIDE {
49 ExtensionServiceTestBase::SetUp();
50 InitializeExtensionService(CreateDefaultInitParams());
51 InitializeProcessManager();
52 }
53
54 protected:
55 // Overridden from views::WidgetObserver:
56 void InstallApp(Profile* profile, const Extension* app) {
57 service()->AddExtension(app);
58 }
59
60 void UninstallApp(const std::string& app_id) {
61 service()->UninstallExtension(app_id,
62 UninstallReason::UNINSTALL_REASON_FOR_TESTING,
63 base::Closure(),
64 NULL);
65 }
66
67 void CreateAppWithPermissions(const std::string id_seed,
scheib 2014/09/23 17:10:54 Do we need an id_seed that varies between tests? C
sashab 2014/09/24 23:23:48 Now uses a constant.
68 ListBuilder& required_permissions,
69 ListBuilder& optional_permissions) {
70 app_ = test_util::BuildApp(ExtensionBuilder().Pass())
71 .MergeManifest(
72 DictionaryBuilder()
73 .Set("permissions", required_permissions)
74 .Set("optional_permissions", optional_permissions))
75 .SetID(crx_file::id_util::GenerateId(id_seed))
76 .SetLocation(Manifest::INTERNAL)
77 .Build();
78 }
79
80 void CreateExtensionWithPermissions(const std::string id_seed,
scheib 2014/09/23 17:10:54 ditto for id_seed here
sashab 2014/09/24 23:23:49 Done.
81 ListBuilder& required_permissions,
82 ListBuilder& optional_permissions) {
83 app_ = test_util::BuildExtension(ExtensionBuilder().Pass())
84 .MergeManifest(
85 DictionaryBuilder()
86 .Set("permissions", required_permissions)
87 .Set("optional_permissions", optional_permissions))
88 .SetID(crx_file::id_util::GenerateId(id_seed))
89 .SetLocation(Manifest::INTERNAL)
90 .Build();
91 }
92
93 scoped_refptr<PermissionSet> PermissionSetFromAPIPermissions(
94 APIPermissionSet& permissions) {
95 scoped_refptr<PermissionSet> permission_set = new PermissionSet(
96 permissions, ManifestPermissionSet(), URLPatternSet(), URLPatternSet());
97 return permission_set;
98 }
99
100 // Returns the permission messages that would display in the prompt that
101 // requests the given permissions for the current |app_|.
102 std::vector<base::string16> OptionalPermissionsRequestPromptMessages(
103 APIPermissionSet& permissions) {
104 scoped_refptr<PermissionSet> permission_set = new PermissionSet(
105 permissions, ManifestPermissionSet(), URLPatternSet(), URLPatternSet());
106 permission_set = PermissionSet::CreateDifference(
107 permission_set.get(), granted_permissions().get());
108 return message_provider_->GetWarningMessages(permission_set.get(),
109 app_->GetType());
110 }
111
112 void GrantPermissions(scoped_refptr<const PermissionSet> permissions) {
113 PermissionsUpdater perms_updater(profile());
114 perms_updater.AddPermissions(app_.get(), permissions.get());
115 }
116
117 scoped_refptr<const PermissionSet> active_permissions() {
118 return app_->permissions_data()->active_permissions();
119 }
120
121 scoped_refptr<const PermissionSet> withheld_permissions() {
122 return app_->permissions_data()->withheld_permissions();
123 }
124
125 scoped_refptr<const PermissionSet> granted_permissions() {
126 return ExtensionPrefs::Get(profile())->GetGrantedPermissions(app_->id());
127 }
128
129 scoped_refptr<const PermissionSet> required_permissions() {
130 return PermissionsParser::GetRequiredPermissions(app_.get());
131 }
132
133 scoped_refptr<const PermissionSet> optional_permissions() {
134 return PermissionsParser::GetOptionalPermissions(app_.get());
135 }
136
137 std::vector<base::string16> messages(
scheib 2014/09/23 17:10:54 Simplify test code by having the 'required_permiss
sashab 2014/09/24 23:23:48 Good idea. Done :)
138 scoped_refptr<const PermissionSet> permissions) {
139 return message_provider_->GetWarningMessages(permissions.get(),
140 app_->GetType());
141 }
142
143 scoped_ptr<ChromePermissionMessageProvider> message_provider_;
144 scoped_refptr<const Extension> app_;
145
146 private:
147 DISALLOW_COPY_AND_ASSIGN(ChromePermissionMessageProviderUnittest);
148 };
149
150 // If an app has both the 'serial' and 'USB' permission, they should coalesce
151 // into a single permission message.
152 TEST_F(ChromePermissionMessageProviderUnittest,
153 RequiredPermissionMessagesCoalesce) {
154 CreateAppWithPermissions("app",
155 ListBuilder().Append("serial").Append("usb").Pass(),
156 ListBuilder().Pass());
157 service()->AddExtension(app_.get());
158
159 std::vector<base::string16> required_permission_messages =
160 messages(required_permissions());
161 ASSERT_EQ(1U, required_permission_messages.size());
162 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_USB_SERIAL),
163 base::UTF16ToUTF8(required_permission_messages[0]));
164
165 std::vector<base::string16> optional_permission_messages =
166 messages(optional_permissions());
167 ASSERT_EQ(0U, optional_permission_messages.size());
168 }
169
170 // If an app has both the 'history' and 'tabs' permission, one should hide the
171 // other (the 'history' permission has superset permissions).
172 TEST_F(ChromePermissionMessageProviderUnittest, HistoryHidesTabsMessage) {
173 CreateExtensionWithPermissions(
174 "app",
175 ListBuilder().Append("tabs").Append("history").Pass(),
176 ListBuilder().Pass());
177 service()->AddExtension(app_.get());
178
179 std::vector<base::string16> required_permission_messages =
180 messages(required_permissions());
181 ASSERT_EQ(1U, required_permission_messages.size());
182 EXPECT_EQ(
183 l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE),
184 base::UTF16ToUTF8(required_permission_messages[0]));
185
186 std::vector<base::string16> optional_permission_messages =
187 messages(optional_permissions());
188 ASSERT_EQ(0U, optional_permission_messages.size());
189 }
190
191 // If an app requests the 'history' permission, but already has the 'tabs'
192 // permission, only the new coalesced message is displayed.
193 TEST_F(ChromePermissionMessageProviderUnittest,
194 MixedPermissionMessagesCoalesceOnceGranted) {
195 CreateExtensionWithPermissions("app",
196 ListBuilder().Append("tabs").Pass(),
197 ListBuilder().Append("history").Pass());
198 service()->AddExtension(app_.get());
199
200 std::vector<base::string16> required_permission_messages =
201 messages(required_permissions());
202 ASSERT_EQ(1U, required_permission_messages.size());
203 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ),
204 base::UTF16ToUTF8(required_permission_messages[0]));
205
206 std::vector<base::string16> optional_permission_messages =
207 messages(optional_permissions());
208 ASSERT_EQ(1U, optional_permission_messages.size());
209 EXPECT_EQ(
210 l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE),
211 base::UTF16ToUTF8(optional_permission_messages[0]));
212
213 std::vector<base::string16> active_permission_messages =
214 messages(active_permissions());
215 ASSERT_EQ(1U, active_permission_messages.size());
216 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ),
217 base::UTF16ToUTF8(active_permission_messages[0]));
218
219 APIPermissionSet requested_optional_permissions;
220 requested_optional_permissions.insert(APIPermission::kHistory);
221 std::vector<base::string16> requested_optional_permission_messages =
222 OptionalPermissionsRequestPromptMessages(requested_optional_permissions);
223 ASSERT_EQ(1U, requested_optional_permission_messages.size());
224 EXPECT_EQ(
225 l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE),
226 base::UTF16ToUTF8(requested_optional_permission_messages[0]));
227
228 GrantPermissions(
229 PermissionSetFromAPIPermissions(requested_optional_permissions));
230
231 active_permission_messages = messages(active_permissions());
232 ASSERT_EQ(1U, active_permission_messages.size());
233 EXPECT_EQ(
234 l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE),
235 base::UTF16ToUTF8(active_permission_messages[0]));
236 }
237
238 // If an app requests the 'tabs' permission but already has the 'history'
239 // permission, a prompt is displayed to request this permission, but it doesn't
240 // appear in the final list of permissions since it is a subset of an already
241 // granted permission.
242 TEST_F(ChromePermissionMessageProviderUnittest,
243 PromptCanRequestSubsetOfAlreadyGrantedPermissions) {
244 CreateExtensionWithPermissions("app",
245 ListBuilder().Append("history").Pass(),
246 ListBuilder().Append("tabs").Pass());
247 service()->AddExtension(app_.get());
248
249 std::vector<base::string16> required_permission_messages =
250 messages(required_permissions());
251 ASSERT_EQ(1U, required_permission_messages.size());
252 EXPECT_EQ(
253 l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE),
254 base::UTF16ToUTF8(required_permission_messages[0]));
255
256 std::vector<base::string16> optional_permission_messages =
257 messages(optional_permissions());
258 ASSERT_EQ(1U, optional_permission_messages.size());
259 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ),
260 base::UTF16ToUTF8(optional_permission_messages[0]));
261
262 std::vector<base::string16> active_permission_messages =
263 messages(active_permissions());
264 ASSERT_EQ(1U, active_permission_messages.size());
265 EXPECT_EQ(
266 l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE),
267 base::UTF16ToUTF8(active_permission_messages[0]));
268
269 APIPermissionSet requested_optional_permissions;
270 requested_optional_permissions.insert(APIPermission::kTab);
271 std::vector<base::string16> requested_optional_permission_messages =
272 OptionalPermissionsRequestPromptMessages(requested_optional_permissions);
273 // TODO(sashab): This prompt should display no permissions, since READ is a
274 // subset permission of WRITE.
275 ASSERT_EQ(1U, requested_optional_permission_messages.size());
276 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ),
277 base::UTF16ToUTF8(requested_optional_permission_messages[0]));
278
279 GrantPermissions(
280 PermissionSetFromAPIPermissions(requested_optional_permissions));
281
282 active_permission_messages = messages(active_permissions());
283 ASSERT_EQ(1U, active_permission_messages.size());
284 EXPECT_EQ(
285 l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE),
286 base::UTF16ToUTF8(active_permission_messages[0]));
287 }
288
289 // If an app requests the 'sessions' permission, nothing is displayed in the
290 // permission request prompt, but the required permissions for the app are
291 // actually modified.
292 TEST_F(ChromePermissionMessageProviderUnittest,
293 PromptCanBeEmptyButCausesChangeInPermissions) {
294 CreateExtensionWithPermissions("app",
295 ListBuilder().Append("tabs").Pass(),
296 ListBuilder().Append("sessions").Pass());
297 service()->AddExtension(app_.get());
298
299 std::vector<base::string16> required_permission_messages =
300 messages(required_permissions());
301 ASSERT_EQ(1U, required_permission_messages.size());
302 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ),
303 base::UTF16ToUTF8(required_permission_messages[0]));
304
305 std::vector<base::string16> optional_permission_messages =
306 messages(optional_permissions());
307 ASSERT_EQ(0U, optional_permission_messages.size());
308
309 std::vector<base::string16> active_permission_messages =
310 messages(active_permissions());
311 ASSERT_EQ(1U, active_permission_messages.size());
312 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ),
313 base::UTF16ToUTF8(active_permission_messages[0]));
314
315 APIPermissionSet requested_optional_permissions;
316 requested_optional_permissions.insert(APIPermission::kSessions);
317 std::vector<base::string16> requested_optional_permission_messages =
318 OptionalPermissionsRequestPromptMessages(requested_optional_permissions);
319 // TODO(sashab): This prompt should display the sessions permission message,
320 // as well as warn the user that it can affect the existing 'tab' permission.
321 ASSERT_EQ(0U, requested_optional_permission_messages.size());
322
323 GrantPermissions(
324 PermissionSetFromAPIPermissions(requested_optional_permissions));
325
326 active_permission_messages = messages(active_permissions());
327 ASSERT_EQ(1U, active_permission_messages.size());
328 EXPECT_EQ(l10n_util::GetStringUTF8(
329 IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ_AND_SESSIONS),
330 base::UTF16ToUTF8(active_permission_messages[0]));
331 }
332
333 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/chrome_tests_unit.gypi ('k') | extensions/common/test_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698