1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/permissions/object_permission_context_base.h"
7 #include "base/strings/strcat.h"
8 #include "components/content_settings/core/browser/host_content_settings_map.h"
9 #include "components/permissions/test/object_permission_context_base_mock_permission_observer.h"
10 #include "components/permissions/test/test_permissions_client.h"
11 #include "content/public/test/browser_task_environment.h"
12 #include "content/public/test/test_browser_context.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "url/origin.h"
18 namespace permissions {
21 const char* kRequiredKey1 = "key-1";
22 const char* kRequiredKey2 = "key-2";
24 class TestObjectPermissionContext : public ObjectPermissionContextBase {
26 // This class uses the USB content settings type for testing purposes only.
27 explicit TestObjectPermissionContext(content::BrowserContext* browser_context)
28 : ObjectPermissionContextBase(
29 ContentSettingsType::USB_GUARD,
30 ContentSettingsType::USB_CHOOSER_DATA,
31 PermissionsClient::Get()->GetSettingsMap(browser_context)) {}
32 ~TestObjectPermissionContext() override = default;
34 bool IsValidObject(const base::Value::Dict& dict) override {
35 return dict.size() == 2 && dict.Find(kRequiredKey1) &&
36 dict.Find(kRequiredKey2);
39 std::u16string GetObjectDisplayName(
40 const base::Value::Dict& object) override {
44 std::string GetKeyForObject(const base::Value::Dict& object) override {
45 return *object.FindString(kRequiredKey1);
51 class ObjectPermissionContextBaseTest : public testing::Test {
53 ObjectPermissionContextBaseTest()
54 : url1_("https://google.com"),
55 url2_("https://chromium.org"),
56 origin1_(url::Origin::Create(url1_)),
57 origin2_(url::Origin::Create(url2_)),
58 context_(browser_context()) {
59 object1_.Set(kRequiredKey1, "value1");
60 object1_.Set(kRequiredKey2, "value2");
61 object2_.Set(kRequiredKey1, "value3");
62 object2_.Set(kRequiredKey2, "value4");
65 ~ObjectPermissionContextBaseTest() override = default;
67 content::BrowserContext* browser_context() { return &browser_context_; }
70 content::BrowserTaskEnvironment task_environment_;
71 content::TestBrowserContext browser_context_;
72 TestPermissionsClient client_;
77 const url::Origin origin1_;
78 const url::Origin origin2_;
79 base::Value::Dict object1_;
80 base::Value::Dict object2_;
81 TestObjectPermissionContext context_;
84 TEST_F(ObjectPermissionContextBaseTest, GrantAndRevokeObjectPermissions) {
85 MockPermissionObserver mock_observer;
86 context_.AddObserver(&mock_observer);
88 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
89 context_.GrantObjectPermission(origin1_, object1_.Clone());
90 context_.GrantObjectPermission(origin1_, object2_.Clone());
92 auto objects = context_.GetGrantedObjects(origin1_);
93 EXPECT_EQ(2u, objects.size());
94 EXPECT_EQ(object1_, objects[0]->value);
95 EXPECT_EQ(object2_, objects[1]->value);
97 // Granting permission to one origin should not grant them to another.
98 objects = context_.GetGrantedObjects(origin2_);
99 EXPECT_EQ(0u, objects.size());
101 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
102 EXPECT_CALL(mock_observer, OnPermissionRevoked(origin1_)).Times(2);
103 context_.RevokeObjectPermission(origin1_, object1_);
104 context_.RevokeObjectPermission(origin1_, object2_);
105 objects = context_.GetGrantedObjects(origin1_);
106 EXPECT_EQ(0u, objects.size());
109 TEST_F(ObjectPermissionContextBaseTest, GrantAndRevokeAllObjectPermissions) {
110 MockPermissionObserver mock_observer;
111 context_.AddObserver(&mock_observer);
113 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(3);
114 context_.GrantObjectPermission(origin1_, object1_.Clone());
115 context_.GrantObjectPermission(origin1_, object2_.Clone());
116 auto objects = context_.GetGrantedObjects(origin1_);
118 EXPECT_CALL(mock_observer, OnPermissionRevoked(origin1_)).Times(1);
119 context_.RevokeObjectPermissions(origin1_);
121 // All permissions have been revoked for the given origin.
122 objects = context_.GetGrantedObjects(origin1_);
123 EXPECT_EQ(0u, objects.size());
126 TEST_F(ObjectPermissionContextBaseTest, GrantObjectPermissionTwice) {
127 MockPermissionObserver mock_observer;
128 context_.AddObserver(&mock_observer);
130 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
131 context_.GrantObjectPermission(origin1_, object1_.Clone());
132 context_.GrantObjectPermission(origin1_, object1_.Clone());
134 auto objects = context_.GetGrantedObjects(origin1_);
135 EXPECT_EQ(1u, objects.size());
136 EXPECT_EQ(object1_, objects[0]->value);
138 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
139 EXPECT_CALL(mock_observer, OnPermissionRevoked(origin1_));
140 context_.RevokeObjectPermission(origin1_, object1_);
141 objects = context_.GetGrantedObjects(origin1_);
142 EXPECT_EQ(0u, objects.size());
145 TEST_F(ObjectPermissionContextBaseTest, GrantAndUpdateObjectPermission) {
146 MockPermissionObserver mock_observer;
147 context_.AddObserver(&mock_observer);
149 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
150 context_.GrantObjectPermission(origin1_, object1_.Clone());
152 auto objects = context_.GetGrantedObjects(origin1_);
153 EXPECT_EQ(1u, objects.size());
154 EXPECT_EQ(object1_, objects[0]->value);
156 testing::Mock::VerifyAndClearExpectations(&mock_observer);
157 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
158 context_.UpdateObjectPermission(origin1_, objects[0]->value,
161 objects = context_.GetGrantedObjects(origin1_);
162 EXPECT_EQ(1u, objects.size());
163 EXPECT_EQ(object2_, objects[0]->value);
166 // UpdateObjectPermission() should not grant new permissions.
167 TEST_F(ObjectPermissionContextBaseTest,
168 UpdateObjectPermissionWithNonExistentPermission) {
169 MockPermissionObserver mock_observer;
170 context_.AddObserver(&mock_observer);
172 // Attempt to update permission for non-existent |object1_| permission.
173 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(0);
174 context_.UpdateObjectPermission(origin1_, object1_, object2_.Clone());
175 testing::Mock::VerifyAndClearExpectations(&mock_observer);
177 auto objects = context_.GetGrantedObjects(origin1_);
178 EXPECT_TRUE(objects.empty());
180 // Grant permission for |object2_| but attempt to update permission for
181 // non-existent |object1_| permission again.
182 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
183 context_.GrantObjectPermission(origin1_, object2_.Clone());
184 testing::Mock::VerifyAndClearExpectations(&mock_observer);
186 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(0);
187 context_.UpdateObjectPermission(origin1_, object1_, object2_.Clone());
188 testing::Mock::VerifyAndClearExpectations(&mock_observer);
190 objects = context_.GetGrantedObjects(origin1_);
191 EXPECT_EQ(1u, objects.size());
192 EXPECT_EQ(object2_, objects[0]->value);
195 TEST_F(ObjectPermissionContextBaseTest, GetOriginsWithGrants) {
196 MockPermissionObserver mock_observer;
197 context_.AddObserver(&mock_observer);
199 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
200 context_.GrantObjectPermission(origin1_, object1_.Clone());
201 context_.GrantObjectPermission(origin2_, object2_.Clone());
203 auto origins_with_grants = context_.GetOriginsWithGrants();
204 EXPECT_EQ(2u, origins_with_grants.size());
205 EXPECT_TRUE(base::Contains(origins_with_grants, origin2_));
206 EXPECT_TRUE(base::Contains(origins_with_grants, origin1_));
209 TEST_F(ObjectPermissionContextBaseTest, GetAllGrantedObjects) {
210 MockPermissionObserver mock_observer;
211 context_.AddObserver(&mock_observer);
213 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
214 context_.GrantObjectPermission(origin1_, object1_.Clone());
215 context_.GrantObjectPermission(origin2_, object2_.Clone());
217 auto objects = context_.GetAllGrantedObjects();
218 EXPECT_EQ(2u, objects.size());
219 EXPECT_EQ(object2_, objects[0]->value);
220 EXPECT_EQ(object1_, objects[1]->value);
223 TEST_F(ObjectPermissionContextBaseTest, GetGrantedObjectsWithGuardBlocked) {
224 auto* map = PermissionsClient::Get()->GetSettingsMap(browser_context());
225 map->SetContentSettingDefaultScope(
226 url1_, url1_, ContentSettingsType::USB_GUARD, CONTENT_SETTING_BLOCK);
228 MockPermissionObserver mock_observer;
229 context_.AddObserver(&mock_observer);
231 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
232 context_.GrantObjectPermission(origin1_, object1_.Clone());
233 context_.GrantObjectPermission(origin2_, object2_.Clone());
235 auto objects1 = context_.GetGrantedObjects(origin1_);
236 EXPECT_EQ(0u, objects1.size());
238 auto objects2 = context_.GetGrantedObjects(origin2_);
239 ASSERT_EQ(1u, objects2.size());
240 EXPECT_EQ(object2_, objects2[0]->value);
243 TEST_F(ObjectPermissionContextBaseTest, GetAllGrantedObjectsWithGuardBlocked) {
244 auto* map = PermissionsClient::Get()->GetSettingsMap(browser_context());
245 map->SetContentSettingDefaultScope(
246 url1_, url1_, ContentSettingsType::USB_GUARD, CONTENT_SETTING_BLOCK);
248 MockPermissionObserver mock_observer;
249 context_.AddObserver(&mock_observer);
251 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
252 context_.GrantObjectPermission(origin1_, object1_.Clone());
253 context_.GrantObjectPermission(origin2_, object2_.Clone());
255 auto objects = context_.GetAllGrantedObjects();
256 ASSERT_EQ(1u, objects.size());
257 EXPECT_EQ(url2_, objects[0]->origin);
258 EXPECT_EQ(object2_, objects[0]->value);
261 TEST_F(ObjectPermissionContextBaseTest, GrantAndRevokeObjectPermissions_Keyed) {
262 MockPermissionObserver mock_observer;
263 context_.AddObserver(&mock_observer);
265 auto object1_key = context_.GetKeyForObject(object1_);
266 auto object2_key = context_.GetKeyForObject(object2_);
268 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
269 context_.GrantObjectPermission(origin1_, object1_.Clone());
270 context_.GrantObjectPermission(origin1_, object2_.Clone());
272 auto objects = context_.GetGrantedObjects(origin1_);
273 EXPECT_EQ(2u, objects.size());
274 EXPECT_EQ(object1_, objects[0]->value);
275 EXPECT_EQ(object2_, objects[1]->value);
277 // Granting permission to one origin should not grant them to another.
278 objects = context_.GetGrantedObjects(origin2_);
279 EXPECT_EQ(0u, objects.size());
281 // Ensure objects can be retrieved individually.
282 EXPECT_EQ(object1_, context_.GetGrantedObject(origin1_, object1_key)->value);
283 EXPECT_EQ(object2_, context_.GetGrantedObject(origin1_, object2_key)->value);
285 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
286 EXPECT_CALL(mock_observer, OnPermissionRevoked(origin1_)).Times(2);
287 context_.RevokeObjectPermission(origin1_, object1_key);
288 context_.RevokeObjectPermission(origin1_, object2_key);
289 EXPECT_EQ(nullptr, context_.GetGrantedObject(origin1_, object1_key));
290 EXPECT_EQ(nullptr, context_.GetGrantedObject(origin1_, object2_key));
291 objects = context_.GetGrantedObjects(origin1_);
292 EXPECT_EQ(0u, objects.size());
295 TEST_F(ObjectPermissionContextBaseTest, GrantObjectPermissionTwice_Keyed) {
296 MockPermissionObserver mock_observer;
297 context_.AddObserver(&mock_observer);
299 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
300 context_.GrantObjectPermission(origin1_, object1_.Clone());
301 context_.GrantObjectPermission(origin1_, object1_.Clone());
303 auto objects = context_.GetGrantedObjects(origin1_);
304 EXPECT_EQ(1u, objects.size());
305 EXPECT_EQ(object1_, objects[0]->value);
307 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
308 EXPECT_CALL(mock_observer, OnPermissionRevoked(origin1_));
309 context_.RevokeObjectPermission(origin1_, context_.GetKeyForObject(object1_));
310 objects = context_.GetGrantedObjects(origin1_);
311 EXPECT_EQ(0u, objects.size());
314 TEST_F(ObjectPermissionContextBaseTest, GrantAndUpdateObjectPermission_Keyed) {
315 MockPermissionObserver mock_observer;
316 context_.AddObserver(&mock_observer);
318 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
319 context_.GrantObjectPermission(origin1_, object1_.Clone());
321 auto objects = context_.GetGrantedObjects(origin1_);
322 EXPECT_EQ(1u, objects.size());
323 EXPECT_EQ(object1_, objects[0]->value);
325 // Update the object without changing the key.
326 std::string new_value("new_value");
327 auto new_object = objects[0]->value.Clone();
328 new_object.Set(kRequiredKey2, new_value);
329 EXPECT_NE(new_object, objects[0]->value);
331 testing::Mock::VerifyAndClearExpectations(&mock_observer);
332 EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
333 // GrantObjectPermission will update an object if an object with the same key
335 context_.GrantObjectPermission(origin1_, new_object.Clone());
337 objects = context_.GetGrantedObjects(origin1_);
338 EXPECT_EQ(1u, objects.size());
339 EXPECT_EQ(new_object, objects[0]->value);
342 } // namespace permissions