1// Copyright 2013 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 "base/pickle.h"
6#include "base/values.h"
7#include "extensions/common/extension_messages.h"
8#include "extensions/common/permissions/api_permission_set.h"
9#include "extensions/common/permissions/permissions_info.h"
10#include "ipc/ipc_message.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace extensions {
14
15TEST(APIPermissionSetTest, General) {
16  APIPermissionSet apis;
17  apis.insert(APIPermission::kTab);
18  apis.insert(APIPermission::kBackground);
19  apis.insert(APIPermission::kProxy);
20  apis.insert(APIPermission::kClipboardWrite);
21  apis.insert(APIPermission::kPlugin);
22
23  EXPECT_EQ(apis.find(APIPermission::kProxy)->id(), APIPermission::kProxy);
24  EXPECT_TRUE(apis.find(APIPermission::kSocket) == apis.end());
25
26  EXPECT_EQ(apis.size(), 5u);
27
28  EXPECT_EQ(apis.erase(APIPermission::kTab), 1u);
29  EXPECT_EQ(apis.size(), 4u);
30
31  EXPECT_EQ(apis.erase(APIPermission::kTab), 0u);
32  EXPECT_EQ(apis.size(), 4u);
33}
34
35TEST(APIPermissionSetTest, CreateUnion) {
36  APIPermission* permission = NULL;
37
38  APIPermissionSet apis1;
39  APIPermissionSet apis2;
40  APIPermissionSet expected_apis;
41  APIPermissionSet result;
42
43  const APIPermissionInfo* permission_info =
44    PermissionsInfo::GetInstance()->GetByID(APIPermission::kSocket);
45  permission = permission_info->CreateAPIPermission();
46  {
47    scoped_ptr<base::ListValue> value(new base::ListValue());
48    value->Append(new base::StringValue("tcp-connect:*.example.com:80"));
49    value->Append(new base::StringValue("udp-bind::8080"));
50    value->Append(new base::StringValue("udp-send-to::8888"));
51    ASSERT_TRUE(permission->FromValue(value.get(), NULL, NULL));
52  }
53
54  // Union with an empty set.
55  apis1.insert(APIPermission::kTab);
56  apis1.insert(APIPermission::kBackground);
57  apis1.insert(permission->Clone());
58  expected_apis.insert(APIPermission::kTab);
59  expected_apis.insert(APIPermission::kBackground);
60  expected_apis.insert(permission);
61
62  APIPermissionSet::Union(apis1, apis2, &result);
63
64  EXPECT_TRUE(apis1.Contains(apis2));
65  EXPECT_TRUE(apis1.Contains(result));
66  EXPECT_FALSE(apis2.Contains(apis1));
67  EXPECT_FALSE(apis2.Contains(result));
68  EXPECT_TRUE(result.Contains(apis1));
69  EXPECT_TRUE(result.Contains(apis2));
70
71  EXPECT_EQ(expected_apis, result);
72
73  // Now use a real second set.
74  apis2.insert(APIPermission::kTab);
75  apis2.insert(APIPermission::kProxy);
76  apis2.insert(APIPermission::kClipboardWrite);
77  apis2.insert(APIPermission::kPlugin);
78
79  permission = permission_info->CreateAPIPermission();
80  {
81    scoped_ptr<base::ListValue> value(new base::ListValue());
82    value->Append(new base::StringValue("tcp-connect:*.example.com:80"));
83    value->Append(new base::StringValue("udp-send-to::8899"));
84    ASSERT_TRUE(permission->FromValue(value.get(), NULL, NULL));
85  }
86  apis2.insert(permission);
87
88  expected_apis.insert(APIPermission::kTab);
89  expected_apis.insert(APIPermission::kProxy);
90  expected_apis.insert(APIPermission::kClipboardWrite);
91  expected_apis.insert(APIPermission::kPlugin);
92
93  permission = permission_info->CreateAPIPermission();
94  {
95    scoped_ptr<base::ListValue> value(new base::ListValue());
96    value->Append(new base::StringValue("tcp-connect:*.example.com:80"));
97    value->Append(new base::StringValue("udp-bind::8080"));
98    value->Append(new base::StringValue("udp-send-to::8888"));
99    value->Append(new base::StringValue("udp-send-to::8899"));
100    ASSERT_TRUE(permission->FromValue(value.get(), NULL, NULL));
101  }
102  // Insert a new socket permission which will replace the old one.
103  expected_apis.insert(permission);
104
105  APIPermissionSet::Union(apis1, apis2, &result);
106
107  EXPECT_FALSE(apis1.Contains(apis2));
108  EXPECT_FALSE(apis1.Contains(result));
109  EXPECT_FALSE(apis2.Contains(apis1));
110  EXPECT_FALSE(apis2.Contains(result));
111  EXPECT_TRUE(result.Contains(apis1));
112  EXPECT_TRUE(result.Contains(apis2));
113
114  EXPECT_EQ(expected_apis, result);
115}
116
117TEST(APIPermissionSetTest, CreateIntersection) {
118  APIPermission* permission = NULL;
119
120  APIPermissionSet apis1;
121  APIPermissionSet apis2;
122  APIPermissionSet expected_apis;
123  APIPermissionSet result;
124
125  const APIPermissionInfo* permission_info =
126    PermissionsInfo::GetInstance()->GetByID(APIPermission::kSocket);
127
128  // Intersection with an empty set.
129  apis1.insert(APIPermission::kTab);
130  apis1.insert(APIPermission::kBackground);
131  permission = permission_info->CreateAPIPermission();
132  {
133    scoped_ptr<base::ListValue> value(new base::ListValue());
134    value->Append(new base::StringValue("tcp-connect:*.example.com:80"));
135    value->Append(new base::StringValue("udp-bind::8080"));
136    value->Append(new base::StringValue("udp-send-to::8888"));
137    ASSERT_TRUE(permission->FromValue(value.get(), NULL, NULL));
138  }
139  apis1.insert(permission);
140
141  APIPermissionSet::Intersection(apis1, apis2, &result);
142  EXPECT_TRUE(apis1.Contains(result));
143  EXPECT_TRUE(apis2.Contains(result));
144  EXPECT_TRUE(apis1.Contains(apis2));
145  EXPECT_FALSE(apis2.Contains(apis1));
146  EXPECT_FALSE(result.Contains(apis1));
147  EXPECT_TRUE(result.Contains(apis2));
148
149  EXPECT_TRUE(result.empty());
150  EXPECT_EQ(expected_apis, result);
151
152  // Now use a real second set.
153  apis2.insert(APIPermission::kTab);
154  apis2.insert(APIPermission::kProxy);
155  apis2.insert(APIPermission::kClipboardWrite);
156  apis2.insert(APIPermission::kPlugin);
157  permission = permission_info->CreateAPIPermission();
158  {
159    scoped_ptr<base::ListValue> value(new base::ListValue());
160    value->Append(new base::StringValue("udp-bind::8080"));
161    value->Append(new base::StringValue("udp-send-to::8888"));
162    value->Append(new base::StringValue("udp-send-to::8899"));
163    ASSERT_TRUE(permission->FromValue(value.get(), NULL, NULL));
164  }
165  apis2.insert(permission);
166
167  expected_apis.insert(APIPermission::kTab);
168  permission = permission_info->CreateAPIPermission();
169  {
170    scoped_ptr<base::ListValue> value(new base::ListValue());
171    value->Append(new base::StringValue("udp-bind::8080"));
172    value->Append(new base::StringValue("udp-send-to::8888"));
173    ASSERT_TRUE(permission->FromValue(value.get(), NULL, NULL));
174  }
175  expected_apis.insert(permission);
176
177  APIPermissionSet::Intersection(apis1, apis2, &result);
178
179  EXPECT_TRUE(apis1.Contains(result));
180  EXPECT_TRUE(apis2.Contains(result));
181  EXPECT_FALSE(apis1.Contains(apis2));
182  EXPECT_FALSE(apis2.Contains(apis1));
183  EXPECT_FALSE(result.Contains(apis1));
184  EXPECT_FALSE(result.Contains(apis2));
185
186  EXPECT_EQ(expected_apis, result);
187}
188
189TEST(APIPermissionSetTest, CreateDifference) {
190  APIPermission* permission = NULL;
191
192  APIPermissionSet apis1;
193  APIPermissionSet apis2;
194  APIPermissionSet expected_apis;
195  APIPermissionSet result;
196
197  const APIPermissionInfo* permission_info =
198    PermissionsInfo::GetInstance()->GetByID(APIPermission::kSocket);
199
200  // Difference with an empty set.
201  apis1.insert(APIPermission::kTab);
202  apis1.insert(APIPermission::kBackground);
203  permission = permission_info->CreateAPIPermission();
204  {
205    scoped_ptr<base::ListValue> value(new base::ListValue());
206    value->Append(new base::StringValue("tcp-connect:*.example.com:80"));
207    value->Append(new base::StringValue("udp-bind::8080"));
208    value->Append(new base::StringValue("udp-send-to::8888"));
209    ASSERT_TRUE(permission->FromValue(value.get(), NULL, NULL));
210  }
211  apis1.insert(permission);
212
213  APIPermissionSet::Difference(apis1, apis2, &result);
214
215  EXPECT_EQ(apis1, result);
216
217  // Now use a real second set.
218  apis2.insert(APIPermission::kTab);
219  apis2.insert(APIPermission::kProxy);
220  apis2.insert(APIPermission::kClipboardWrite);
221  apis2.insert(APIPermission::kPlugin);
222  permission = permission_info->CreateAPIPermission();
223  {
224    scoped_ptr<base::ListValue> value(new base::ListValue());
225    value->Append(new base::StringValue("tcp-connect:*.example.com:80"));
226    value->Append(new base::StringValue("udp-send-to::8899"));
227    ASSERT_TRUE(permission->FromValue(value.get(), NULL, NULL));
228  }
229  apis2.insert(permission);
230
231  expected_apis.insert(APIPermission::kBackground);
232  permission = permission_info->CreateAPIPermission();
233  {
234    scoped_ptr<base::ListValue> value(new base::ListValue());
235    value->Append(new base::StringValue("udp-bind::8080"));
236    value->Append(new base::StringValue("udp-send-to::8888"));
237    ASSERT_TRUE(permission->FromValue(value.get(), NULL, NULL));
238  }
239  expected_apis.insert(permission);
240
241  APIPermissionSet::Difference(apis1, apis2, &result);
242
243  EXPECT_TRUE(apis1.Contains(result));
244  EXPECT_FALSE(apis2.Contains(result));
245
246  EXPECT_EQ(expected_apis, result);
247
248  // |result| = |apis1| - |apis2| --> |result| intersect |apis2| == empty_set
249  APIPermissionSet result2;
250  APIPermissionSet::Intersection(result, apis2, &result2);
251  EXPECT_TRUE(result2.empty());
252}
253
254TEST(APIPermissionSetTest, IPC) {
255  APIPermission* permission = NULL;
256
257  APIPermissionSet apis;
258  APIPermissionSet expected_apis;
259
260  const APIPermissionInfo* permission_info =
261    PermissionsInfo::GetInstance()->GetByID(APIPermission::kSocket);
262
263  apis.insert(APIPermission::kTab);
264  apis.insert(APIPermission::kBackground);
265  permission = permission_info->CreateAPIPermission();
266  {
267    scoped_ptr<base::ListValue> value(new base::ListValue());
268    value->Append(new base::StringValue("tcp-connect:*.example.com:80"));
269    value->Append(new base::StringValue("udp-bind::8080"));
270    value->Append(new base::StringValue("udp-send-to::8888"));
271    ASSERT_TRUE(permission->FromValue(value.get(), NULL, NULL));
272  }
273  apis.insert(permission);
274
275  EXPECT_NE(apis, expected_apis);
276
277  IPC::Message m;
278  WriteParam(&m, apis);
279  PickleIterator iter(m);
280  CHECK(ReadParam(&m, &iter, &expected_apis));
281  EXPECT_EQ(apis, expected_apis);
282}
283
284TEST(APIPermissionSetTest, ImplicitPermissions) {
285  APIPermissionSet apis;
286  apis.insert(APIPermission::kFileSystemWrite);
287  apis.AddImpliedPermissions();
288
289  EXPECT_EQ(apis.find(APIPermission::kFileSystemWrite)->id(),
290            APIPermission::kFileSystemWrite);
291  EXPECT_EQ(apis.size(), 1u);
292
293  apis.erase(APIPermission::kFileSystemWrite);
294  apis.insert(APIPermission::kFileSystemDirectory);
295  apis.AddImpliedPermissions();
296
297  EXPECT_EQ(apis.find(APIPermission::kFileSystemDirectory)->id(),
298            APIPermission::kFileSystemDirectory);
299  EXPECT_EQ(apis.size(), 1u);
300
301  apis.insert(APIPermission::kFileSystemWrite);
302  apis.AddImpliedPermissions();
303
304  EXPECT_EQ(apis.find(APIPermission::kFileSystemWrite)->id(),
305            APIPermission::kFileSystemWrite);
306  EXPECT_EQ(apis.find(APIPermission::kFileSystemDirectory)->id(),
307            APIPermission::kFileSystemDirectory);
308  EXPECT_EQ(apis.find(APIPermission::kFileSystemWriteDirectory)->id(),
309            APIPermission::kFileSystemWriteDirectory);
310  EXPECT_EQ(apis.size(), 3u);
311}
312
313}  // namespace extensions
314