permission_set_unittest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
1// Copyright (c) 2012 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/command_line.h"
6#include "base/json/json_file_value_serializer.h"
7#include "base/logging.h"
8#include "base/path_service.h"
9#include "base/utf_string_conversions.h"
10#include "chrome/common/chrome_paths.h"
11#include "chrome/common/chrome_switches.h"
12#include "chrome/common/extensions/extension.h"
13#include "chrome/common/extensions/extension_test_util.h"
14#include "chrome/common/extensions/features/feature.h"
15#include "chrome/common/extensions/permissions/permission_set.h"
16#include "chrome/common/extensions/permissions/permissions_data.h"
17#include "chrome/common/extensions/permissions/permissions_info.h"
18#include "chrome/common/extensions/permissions/socket_permission.h"
19#include "extensions/common/error_utils.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
22using extension_test_util::LoadManifest;
23
24namespace extensions {
25
26namespace {
27
28static void AddPattern(URLPatternSet* extent, const std::string& pattern) {
29  int schemes = URLPattern::SCHEME_ALL;
30  extent->AddPattern(URLPattern(schemes, pattern));
31}
32
33size_t IndexOf(const std::vector<string16>& warnings,
34               const std::string& warning) {
35  for (size_t i = 0; i < warnings.size(); ++i) {
36    if (warnings[i] == ASCIIToUTF16(warning))
37      return i;
38  }
39
40  return warnings.size();
41}
42
43bool Contains(const std::vector<string16>& warnings,
44              const std::string& warning) {
45  return IndexOf(warnings, warning) != warnings.size();
46}
47
48}  // namespace
49
50// Tests GetByID.
51TEST(PermissionsTest, GetByID) {
52  PermissionsInfo* info = PermissionsInfo::GetInstance();
53  APIPermissionSet apis = info->GetAll();
54  for (APIPermissionSet::const_iterator i = apis.begin();
55       i != apis.end(); ++i) {
56    EXPECT_EQ(i->id(), i->info()->id());
57  }
58}
59
60// Tests that GetByName works with normal permission names and aliases.
61TEST(PermissionsTest, GetByName) {
62  PermissionsInfo* info = PermissionsInfo::GetInstance();
63  EXPECT_EQ(APIPermission::kTab, info->GetByName("tabs")->id());
64  EXPECT_EQ(APIPermission::kManagement,
65            info->GetByName("management")->id());
66  EXPECT_FALSE(info->GetByName("alsdkfjasldkfj"));
67}
68
69TEST(PermissionsTest, GetAll) {
70  size_t count = 0;
71  PermissionsInfo* info = PermissionsInfo::GetInstance();
72  APIPermissionSet apis = info->GetAll();
73  for (APIPermissionSet::const_iterator api = apis.begin();
74       api != apis.end(); ++api) {
75    // Make sure only the valid permission IDs get returned.
76    EXPECT_NE(APIPermission::kInvalid, api->id());
77    EXPECT_NE(APIPermission::kUnknown, api->id());
78    count++;
79  }
80  EXPECT_EQ(count, info->get_permission_count());
81}
82
83TEST(PermissionsTest, GetAllByName) {
84  std::set<std::string> names;
85  names.insert("background");
86  names.insert("management");
87
88  // This is an alias of kTab
89  names.insert("windows");
90
91  // This unknown name should get dropped.
92  names.insert("sdlkfjasdlkfj");
93
94  APIPermissionSet expected;
95  expected.insert(APIPermission::kBackground);
96  expected.insert(APIPermission::kManagement);
97  expected.insert(APIPermission::kTab);
98
99  EXPECT_EQ(expected,
100            PermissionsInfo::GetInstance()->GetAllByName(names));
101}
102
103// Tests that the aliases are properly mapped.
104TEST(PermissionsTest, Aliases) {
105  PermissionsInfo* info = PermissionsInfo::GetInstance();
106  // tabs: tabs, windows
107  std::string tabs_name = "tabs";
108  EXPECT_EQ(tabs_name, info->GetByID(APIPermission::kTab)->name());
109  EXPECT_EQ(APIPermission::kTab, info->GetByName("tabs")->id());
110  EXPECT_EQ(APIPermission::kTab, info->GetByName("windows")->id());
111
112  // unlimitedStorage: unlimitedStorage, unlimited_storage
113  std::string storage_name = "unlimitedStorage";
114  EXPECT_EQ(storage_name, info->GetByID(
115      APIPermission::kUnlimitedStorage)->name());
116  EXPECT_EQ(APIPermission::kUnlimitedStorage,
117            info->GetByName("unlimitedStorage")->id());
118  EXPECT_EQ(APIPermission::kUnlimitedStorage,
119            info->GetByName("unlimited_storage")->id());
120}
121
122TEST(PermissionsTest, EffectiveHostPermissions) {
123  scoped_refptr<Extension> extension;
124  scoped_refptr<const PermissionSet> permissions;
125
126  extension = LoadManifest("effective_host_permissions", "empty.json");
127  permissions = extension->GetActivePermissions();
128  EXPECT_EQ(
129      0u,
130      PermissionsData::GetEffectiveHostPermissions(
131          extension).patterns().size());
132  EXPECT_FALSE(permissions->HasEffectiveAccessToURL(
133      GURL("http://www.google.com")));
134  EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
135
136  extension = LoadManifest("effective_host_permissions", "one_host.json");
137  permissions = extension->GetActivePermissions();
138  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
139      GURL("http://www.google.com")));
140  EXPECT_FALSE(permissions->HasEffectiveAccessToURL(
141      GURL("https://www.google.com")));
142  EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
143
144  extension = LoadManifest("effective_host_permissions",
145                           "one_host_wildcard.json");
146  permissions = extension->GetActivePermissions();
147  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://google.com")));
148  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
149      GURL("http://foo.google.com")));
150  EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
151
152  extension = LoadManifest("effective_host_permissions", "two_hosts.json");
153  permissions = extension->GetActivePermissions();
154  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
155      GURL("http://www.google.com")));
156  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
157      GURL("http://www.reddit.com")));
158  EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
159
160  extension = LoadManifest("effective_host_permissions",
161                           "https_not_considered.json");
162  permissions = extension->GetActivePermissions();
163  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://google.com")));
164  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("https://google.com")));
165  EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
166
167  extension = LoadManifest("effective_host_permissions",
168                           "two_content_scripts.json");
169  permissions = extension->GetActivePermissions();
170  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://google.com")));
171  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
172      GURL("http://www.reddit.com")));
173  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
174      GURL("http://news.ycombinator.com")));
175  EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
176
177  extension = LoadManifest("effective_host_permissions", "all_hosts.json");
178  permissions = extension->GetActivePermissions();
179  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://test/")));
180  EXPECT_FALSE(permissions->HasEffectiveAccessToURL(GURL("https://test/")));
181  EXPECT_TRUE(
182      permissions->HasEffectiveAccessToURL(GURL("http://www.google.com")));
183  EXPECT_TRUE(permissions->HasEffectiveAccessToAllHosts());
184
185  extension = LoadManifest("effective_host_permissions", "all_hosts2.json");
186  permissions = extension->GetActivePermissions();
187  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://test/")));
188  EXPECT_TRUE(
189      permissions->HasEffectiveAccessToURL(GURL("http://www.google.com")));
190  EXPECT_TRUE(permissions->HasEffectiveAccessToAllHosts());
191
192  extension = LoadManifest("effective_host_permissions", "all_hosts3.json");
193  permissions = extension->GetActivePermissions();
194  EXPECT_FALSE(permissions->HasEffectiveAccessToURL(GURL("http://test/")));
195  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("https://test/")));
196  EXPECT_TRUE(
197      permissions->HasEffectiveAccessToURL(GURL("http://www.google.com")));
198  EXPECT_TRUE(permissions->HasEffectiveAccessToAllHosts());
199}
200
201TEST(PermissionsTest, ExplicitAccessToOrigin) {
202  APIPermissionSet apis;
203  URLPatternSet explicit_hosts;
204  URLPatternSet scriptable_hosts;
205
206  AddPattern(&explicit_hosts, "http://*.google.com/*");
207  // The explicit host paths should get set to /*.
208  AddPattern(&explicit_hosts, "http://www.example.com/a/particular/path/*");
209
210  scoped_refptr<PermissionSet> perm_set = new PermissionSet(
211      apis, explicit_hosts, scriptable_hosts);
212  ASSERT_TRUE(perm_set->HasExplicitAccessToOrigin(
213      GURL("http://www.google.com/")));
214  ASSERT_TRUE(perm_set->HasExplicitAccessToOrigin(
215      GURL("http://test.google.com/")));
216  ASSERT_TRUE(perm_set->HasExplicitAccessToOrigin(
217      GURL("http://www.example.com")));
218  ASSERT_TRUE(perm_set->HasEffectiveAccessToURL(
219      GURL("http://www.example.com")));
220  ASSERT_FALSE(perm_set->HasExplicitAccessToOrigin(
221      GURL("http://test.example.com")));
222}
223
224TEST(PermissionsTest, CreateUnion) {
225  APIPermission* permission = NULL;
226
227  APIPermissionSet apis1;
228  APIPermissionSet apis2;
229  APIPermissionSet expected_apis;
230
231  URLPatternSet explicit_hosts1;
232  URLPatternSet explicit_hosts2;
233  URLPatternSet expected_explicit_hosts;
234
235  URLPatternSet scriptable_hosts1;
236  URLPatternSet scriptable_hosts2;
237  URLPatternSet expected_scriptable_hosts;
238
239  URLPatternSet effective_hosts;
240
241  scoped_refptr<PermissionSet> set1;
242  scoped_refptr<PermissionSet> set2;
243  scoped_refptr<PermissionSet> union_set;
244
245  const APIPermissionInfo* permission_info =
246    PermissionsInfo::GetInstance()->GetByID(APIPermission::kSocket);
247  permission = permission_info->CreateAPIPermission();
248  {
249    scoped_ptr<ListValue> value(new ListValue());
250    value->Append(Value::CreateStringValue("tcp-connect:*.example.com:80"));
251    value->Append(Value::CreateStringValue("udp-bind::8080"));
252    value->Append(Value::CreateStringValue("udp-send-to::8888"));
253    if (!permission->FromValue(value.get())) {
254      NOTREACHED();
255    }
256  }
257
258  // Union with an empty set.
259  apis1.insert(APIPermission::kTab);
260  apis1.insert(APIPermission::kBackground);
261  apis1.insert(permission->Clone());
262  expected_apis.insert(APIPermission::kTab);
263  expected_apis.insert(APIPermission::kBackground);
264  expected_apis.insert(permission);
265
266  AddPattern(&explicit_hosts1, "http://*.google.com/*");
267  AddPattern(&expected_explicit_hosts, "http://*.google.com/*");
268  AddPattern(&effective_hosts, "http://*.google.com/*");
269
270  set1 = new PermissionSet(apis1, explicit_hosts1, scriptable_hosts1);
271  set2 = new PermissionSet(apis2, explicit_hosts2, scriptable_hosts2);
272  union_set = PermissionSet::CreateUnion(set1.get(), set2.get());
273  EXPECT_TRUE(set1->Contains(*set2));
274  EXPECT_TRUE(set1->Contains(*union_set));
275  EXPECT_FALSE(set2->Contains(*set1));
276  EXPECT_FALSE(set2->Contains(*union_set));
277  EXPECT_TRUE(union_set->Contains(*set1));
278  EXPECT_TRUE(union_set->Contains(*set2));
279
280  EXPECT_FALSE(union_set->HasEffectiveFullAccess());
281  EXPECT_EQ(expected_apis, union_set->apis());
282  EXPECT_EQ(expected_explicit_hosts, union_set->explicit_hosts());
283  EXPECT_EQ(expected_scriptable_hosts, union_set->scriptable_hosts());
284  EXPECT_EQ(expected_explicit_hosts, union_set->effective_hosts());
285
286  // Now use a real second set.
287  apis2.insert(APIPermission::kTab);
288  apis2.insert(APIPermission::kProxy);
289  apis2.insert(APIPermission::kClipboardWrite);
290  apis2.insert(APIPermission::kPlugin);
291
292  permission = permission_info->CreateAPIPermission();
293  {
294    scoped_ptr<ListValue> value(new ListValue());
295    value->Append(Value::CreateStringValue("tcp-connect:*.example.com:80"));
296    value->Append(Value::CreateStringValue("udp-send-to::8899"));
297    if (!permission->FromValue(value.get())) {
298      NOTREACHED();
299    }
300  }
301  apis2.insert(permission);
302
303  expected_apis.insert(APIPermission::kTab);
304  expected_apis.insert(APIPermission::kProxy);
305  expected_apis.insert(APIPermission::kClipboardWrite);
306  expected_apis.insert(APIPermission::kPlugin);
307
308  permission = permission_info->CreateAPIPermission();
309  {
310    scoped_ptr<ListValue> value(new ListValue());
311    value->Append(Value::CreateStringValue("tcp-connect:*.example.com:80"));
312    value->Append(Value::CreateStringValue("udp-bind::8080"));
313    value->Append(Value::CreateStringValue("udp-send-to::8888"));
314    value->Append(Value::CreateStringValue("udp-send-to::8899"));
315    if (!permission->FromValue(value.get())) {
316      NOTREACHED();
317    }
318  }
319  // Insert a new permission socket permisssion which will replace the old one.
320  expected_apis.insert(permission);
321
322  AddPattern(&explicit_hosts2, "http://*.example.com/*");
323  AddPattern(&scriptable_hosts2, "http://*.google.com/*");
324  AddPattern(&expected_explicit_hosts, "http://*.example.com/*");
325  AddPattern(&expected_scriptable_hosts, "http://*.google.com/*");
326
327  URLPatternSet::CreateUnion(
328      explicit_hosts2, scriptable_hosts2, &effective_hosts);
329
330  set2 = new PermissionSet(apis2, explicit_hosts2, scriptable_hosts2);
331  union_set = PermissionSet::CreateUnion(set1.get(), set2.get());
332
333  EXPECT_FALSE(set1->Contains(*set2));
334  EXPECT_FALSE(set1->Contains(*union_set));
335  EXPECT_FALSE(set2->Contains(*set1));
336  EXPECT_FALSE(set2->Contains(*union_set));
337  EXPECT_TRUE(union_set->Contains(*set1));
338  EXPECT_TRUE(union_set->Contains(*set2));
339
340  EXPECT_TRUE(union_set->HasEffectiveFullAccess());
341  EXPECT_TRUE(union_set->HasEffectiveAccessToAllHosts());
342  EXPECT_EQ(expected_apis, union_set->apis());
343  EXPECT_EQ(expected_explicit_hosts, union_set->explicit_hosts());
344  EXPECT_EQ(expected_scriptable_hosts, union_set->scriptable_hosts());
345  EXPECT_EQ(effective_hosts, union_set->effective_hosts());
346}
347
348TEST(PermissionsTest, CreateIntersection) {
349  APIPermission* permission = NULL;
350
351  APIPermissionSet apis1;
352  APIPermissionSet apis2;
353  APIPermissionSet expected_apis;
354
355  URLPatternSet explicit_hosts1;
356  URLPatternSet explicit_hosts2;
357  URLPatternSet expected_explicit_hosts;
358
359  URLPatternSet scriptable_hosts1;
360  URLPatternSet scriptable_hosts2;
361  URLPatternSet expected_scriptable_hosts;
362
363  URLPatternSet effective_hosts;
364
365  scoped_refptr<PermissionSet> set1;
366  scoped_refptr<PermissionSet> set2;
367  scoped_refptr<PermissionSet> new_set;
368
369  const APIPermissionInfo* permission_info =
370    PermissionsInfo::GetInstance()->GetByID(APIPermission::kSocket);
371
372  // Intersection with an empty set.
373  apis1.insert(APIPermission::kTab);
374  apis1.insert(APIPermission::kBackground);
375  permission = permission_info->CreateAPIPermission();
376  {
377    scoped_ptr<ListValue> value(new ListValue());
378    value->Append(Value::CreateStringValue("tcp-connect:*.example.com:80"));
379    value->Append(Value::CreateStringValue("udp-bind::8080"));
380    value->Append(Value::CreateStringValue("udp-send-to::8888"));
381    if (!permission->FromValue(value.get())) {
382      NOTREACHED();
383    }
384  }
385  apis1.insert(permission);
386
387  AddPattern(&explicit_hosts1, "http://*.google.com/*");
388  AddPattern(&scriptable_hosts1, "http://www.reddit.com/*");
389
390  set1 = new PermissionSet(apis1, explicit_hosts1, scriptable_hosts1);
391  set2 = new PermissionSet(apis2, explicit_hosts2, scriptable_hosts2);
392  new_set = PermissionSet::CreateIntersection(set1.get(), set2.get());
393  EXPECT_TRUE(set1->Contains(*new_set));
394  EXPECT_TRUE(set2->Contains(*new_set));
395  EXPECT_TRUE(set1->Contains(*set2));
396  EXPECT_FALSE(set2->Contains(*set1));
397  EXPECT_FALSE(new_set->Contains(*set1));
398  EXPECT_TRUE(new_set->Contains(*set2));
399
400  EXPECT_TRUE(new_set->IsEmpty());
401  EXPECT_FALSE(new_set->HasEffectiveFullAccess());
402  EXPECT_EQ(expected_apis, new_set->apis());
403  EXPECT_EQ(expected_explicit_hosts, new_set->explicit_hosts());
404  EXPECT_EQ(expected_scriptable_hosts, new_set->scriptable_hosts());
405  EXPECT_EQ(expected_explicit_hosts, new_set->effective_hosts());
406
407  // Now use a real second set.
408  apis2.insert(APIPermission::kTab);
409  apis2.insert(APIPermission::kProxy);
410  apis2.insert(APIPermission::kClipboardWrite);
411  apis2.insert(APIPermission::kPlugin);
412  permission = permission_info->CreateAPIPermission();
413  {
414    scoped_ptr<ListValue> value(new ListValue());
415    value->Append(Value::CreateStringValue("udp-bind::8080"));
416    value->Append(Value::CreateStringValue("udp-send-to::8888"));
417    value->Append(Value::CreateStringValue("udp-send-to::8899"));
418    if (!permission->FromValue(value.get())) {
419      NOTREACHED();
420    }
421  }
422  apis2.insert(permission);
423
424  expected_apis.insert(APIPermission::kTab);
425  permission = permission_info->CreateAPIPermission();
426  {
427    scoped_ptr<ListValue> value(new ListValue());
428    value->Append(Value::CreateStringValue("udp-bind::8080"));
429    value->Append(Value::CreateStringValue("udp-send-to::8888"));
430    if (!permission->FromValue(value.get())) {
431      NOTREACHED();
432    }
433  }
434  expected_apis.insert(permission);
435
436  AddPattern(&explicit_hosts2, "http://*.example.com/*");
437  AddPattern(&explicit_hosts2, "http://*.google.com/*");
438  AddPattern(&scriptable_hosts2, "http://*.google.com/*");
439  AddPattern(&expected_explicit_hosts, "http://*.google.com/*");
440
441  effective_hosts.ClearPatterns();
442  AddPattern(&effective_hosts, "http://*.google.com/*");
443
444  set2 = new PermissionSet(apis2, explicit_hosts2, scriptable_hosts2);
445  new_set = PermissionSet::CreateIntersection(set1.get(), set2.get());
446
447  EXPECT_TRUE(set1->Contains(*new_set));
448  EXPECT_TRUE(set2->Contains(*new_set));
449  EXPECT_FALSE(set1->Contains(*set2));
450  EXPECT_FALSE(set2->Contains(*set1));
451  EXPECT_FALSE(new_set->Contains(*set1));
452  EXPECT_FALSE(new_set->Contains(*set2));
453
454  EXPECT_FALSE(new_set->HasEffectiveFullAccess());
455  EXPECT_FALSE(new_set->HasEffectiveAccessToAllHosts());
456  EXPECT_EQ(expected_apis, new_set->apis());
457  EXPECT_EQ(expected_explicit_hosts, new_set->explicit_hosts());
458  EXPECT_EQ(expected_scriptable_hosts, new_set->scriptable_hosts());
459  EXPECT_EQ(effective_hosts, new_set->effective_hosts());
460}
461
462TEST(PermissionsTest, CreateDifference) {
463  APIPermission* permission = NULL;
464
465  APIPermissionSet apis1;
466  APIPermissionSet apis2;
467  APIPermissionSet expected_apis;
468
469  URLPatternSet explicit_hosts1;
470  URLPatternSet explicit_hosts2;
471  URLPatternSet expected_explicit_hosts;
472
473  URLPatternSet scriptable_hosts1;
474  URLPatternSet scriptable_hosts2;
475  URLPatternSet expected_scriptable_hosts;
476
477  URLPatternSet effective_hosts;
478
479  scoped_refptr<PermissionSet> set1;
480  scoped_refptr<PermissionSet> set2;
481  scoped_refptr<PermissionSet> new_set;
482
483  const APIPermissionInfo* permission_info =
484    PermissionsInfo::GetInstance()->GetByID(APIPermission::kSocket);
485
486  // Difference with an empty set.
487  apis1.insert(APIPermission::kTab);
488  apis1.insert(APIPermission::kBackground);
489  permission = permission_info->CreateAPIPermission();
490  {
491    scoped_ptr<ListValue> value(new ListValue());
492    value->Append(Value::CreateStringValue("tcp-connect:*.example.com:80"));
493    value->Append(Value::CreateStringValue("udp-bind::8080"));
494    value->Append(Value::CreateStringValue("udp-send-to::8888"));
495    if (!permission->FromValue(value.get())) {
496      NOTREACHED();
497    }
498  }
499  apis1.insert(permission);
500
501  AddPattern(&explicit_hosts1, "http://*.google.com/*");
502  AddPattern(&scriptable_hosts1, "http://www.reddit.com/*");
503
504  set1 = new PermissionSet(apis1, explicit_hosts1, scriptable_hosts1);
505  set2 = new PermissionSet(apis2, explicit_hosts2, scriptable_hosts2);
506  new_set = PermissionSet::CreateDifference(set1.get(), set2.get());
507  EXPECT_EQ(*set1, *new_set);
508
509  // Now use a real second set.
510  apis2.insert(APIPermission::kTab);
511  apis2.insert(APIPermission::kProxy);
512  apis2.insert(APIPermission::kClipboardWrite);
513  apis2.insert(APIPermission::kPlugin);
514  permission = permission_info->CreateAPIPermission();
515  {
516    scoped_ptr<ListValue> value(new ListValue());
517    value->Append(Value::CreateStringValue("tcp-connect:*.example.com:80"));
518    value->Append(Value::CreateStringValue("udp-send-to::8899"));
519    if (!permission->FromValue(value.get())) {
520      NOTREACHED();
521    }
522  }
523  apis2.insert(permission);
524
525  expected_apis.insert(APIPermission::kBackground);
526  permission = permission_info->CreateAPIPermission();
527  {
528    scoped_ptr<ListValue> value(new ListValue());
529    value->Append(Value::CreateStringValue("udp-bind::8080"));
530    value->Append(Value::CreateStringValue("udp-send-to::8888"));
531    if (!permission->FromValue(value.get())) {
532      NOTREACHED();
533    }
534  }
535  expected_apis.insert(permission);
536
537  AddPattern(&explicit_hosts2, "http://*.example.com/*");
538  AddPattern(&explicit_hosts2, "http://*.google.com/*");
539  AddPattern(&scriptable_hosts2, "http://*.google.com/*");
540  AddPattern(&expected_scriptable_hosts, "http://www.reddit.com/*");
541
542  effective_hosts.ClearPatterns();
543  AddPattern(&effective_hosts, "http://www.reddit.com/*");
544
545  set2 = new PermissionSet(apis2, explicit_hosts2, scriptable_hosts2);
546  new_set = PermissionSet::CreateDifference(set1.get(), set2.get());
547
548  EXPECT_TRUE(set1->Contains(*new_set));
549  EXPECT_FALSE(set2->Contains(*new_set));
550
551  EXPECT_FALSE(new_set->HasEffectiveFullAccess());
552  EXPECT_FALSE(new_set->HasEffectiveAccessToAllHosts());
553  EXPECT_EQ(expected_apis, new_set->apis());
554  EXPECT_EQ(expected_explicit_hosts, new_set->explicit_hosts());
555  EXPECT_EQ(expected_scriptable_hosts, new_set->scriptable_hosts());
556  EXPECT_EQ(effective_hosts, new_set->effective_hosts());
557
558  // |set3| = |set1| - |set2| --> |set3| intersect |set2| == empty_set
559  set1 = PermissionSet::CreateIntersection(new_set.get(), set2.get());
560  EXPECT_TRUE(set1->IsEmpty());
561}
562
563TEST(PermissionsTest, HasLessPrivilegesThan) {
564  const struct {
565    const char* base_name;
566    bool expect_increase;
567  } kTests[] = {
568    { "allhosts1", false },  // all -> all
569    { "allhosts2", false },  // all -> one
570    { "allhosts3", true },  // one -> all
571    { "hosts1", false },  // http://a,http://b -> http://a,http://b
572    { "hosts2", true },  // http://a,http://b -> https://a,http://*.b
573    { "hosts3", false },  // http://a,http://b -> http://a
574    { "hosts4", true },  // http://a -> http://a,http://b
575    { "hosts5", false },  // http://a,b,c -> http://a,b,c + https://a,b,c
576    { "hosts6", false },  // http://a.com -> http://a.com + http://a.co.uk
577    { "permissions1", false },  // tabs -> tabs
578    { "permissions2", true },  // tabs -> tabs,bookmarks
579    { "permissions3", true },  // http://a -> http://a,tabs
580    { "permissions5", true },  // bookmarks -> bookmarks,history
581    { "equivalent_warnings", false },  // tabs --> tabs, webNavigation
582#if !defined(OS_CHROMEOS)  // plugins aren't allowed in ChromeOS
583    { "permissions4", false },  // plugin -> plugin,tabs
584    { "plugin1", false },  // plugin -> plugin
585    { "plugin2", false },  // plugin -> none
586    { "plugin3", true },  // none -> plugin
587#endif
588    { "storage", false },  // none -> storage
589    { "notifications", false },  // none -> notifications
590  };
591
592  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) {
593    scoped_refptr<Extension> old_extension(
594        LoadManifest("allow_silent_upgrade",
595                     std::string(kTests[i].base_name) + "_old.json"));
596    scoped_refptr<Extension> new_extension(
597        LoadManifest("allow_silent_upgrade",
598                     std::string(kTests[i].base_name) + "_new.json"));
599
600    EXPECT_TRUE(new_extension.get()) << kTests[i].base_name << "_new.json";
601    if (!new_extension.get())
602      continue;
603
604    scoped_refptr<const PermissionSet> old_p(
605        old_extension->GetActivePermissions());
606    scoped_refptr<const PermissionSet> new_p(
607        new_extension->GetActivePermissions());
608
609    EXPECT_EQ(kTests[i].expect_increase,
610              old_p->HasLessPrivilegesThan(new_p)) << kTests[i].base_name;
611  }
612}
613
614TEST(PermissionsTest, PermissionMessages) {
615  // Ensure that all permissions that needs to show install UI actually have
616  // strings associated with them.
617  APIPermissionSet skip;
618
619  // These are considered "nuisance" or "trivial" permissions that don't need
620  // a prompt.
621  skip.insert(APIPermission::kActiveTab);
622  skip.insert(APIPermission::kAdView);
623  skip.insert(APIPermission::kAlarms);
624  skip.insert(APIPermission::kAppCurrentWindowInternal);
625  skip.insert(APIPermission::kAppRuntime);
626  skip.insert(APIPermission::kAppWindow);
627  skip.insert(APIPermission::kAudio);
628  skip.insert(APIPermission::kBrowsingData);
629  skip.insert(APIPermission::kContextMenus);
630  skip.insert(APIPermission::kFontSettings);
631  skip.insert(APIPermission::kFullscreen);
632  skip.insert(APIPermission::kIdle);
633  skip.insert(APIPermission::kNotification);
634  skip.insert(APIPermission::kPointerLock);
635  skip.insert(APIPermission::kPower);
636  skip.insert(APIPermission::kPushMessaging);
637  skip.insert(APIPermission::kSessionRestore);
638  skip.insert(APIPermission::kScreensaver);
639  skip.insert(APIPermission::kStorage);
640  skip.insert(APIPermission::kSystemInfoDisplay);
641  skip.insert(APIPermission::kTts);
642  skip.insert(APIPermission::kUnlimitedStorage);
643  skip.insert(APIPermission::kWebView);
644
645  // TODO(erikkay) add a string for this permission.
646  skip.insert(APIPermission::kBackground);
647
648  skip.insert(APIPermission::kClipboardWrite);
649
650  // The cookie permission does nothing unless you have associated host
651  // permissions.
652  skip.insert(APIPermission::kCookie);
653
654  // These are warned as part of host permission checks.
655  skip.insert(APIPermission::kDeclarativeContent);
656  skip.insert(APIPermission::kDeclarativeWebRequest);
657  skip.insert(APIPermission::kNativeMessaging);
658  skip.insert(APIPermission::kPageCapture);
659  skip.insert(APIPermission::kProxy);
660  skip.insert(APIPermission::kTabCapture);
661  skip.insert(APIPermission::kWebRequest);
662  skip.insert(APIPermission::kWebRequestBlocking);
663
664  // This permission requires explicit user action (context menu handler)
665  // so we won't prompt for it for now.
666  skip.insert(APIPermission::kFileBrowserHandler);
667
668  // These permissions require explicit user action (configuration dialog)
669  // so we don't prompt for them at install time.
670  skip.insert(APIPermission::kMediaGalleries);
671
672  // If you've turned on the experimental command-line flag, we don't need
673  // to warn you further.
674  skip.insert(APIPermission::kExperimental);
675
676  // The Identity API has its own server-driven permission prompts.
677  skip.insert(APIPermission::kIdentity);
678
679  // These are private.
680  skip.insert(APIPermission::kAutoTestPrivate);
681  skip.insert(APIPermission::kBookmarkManagerPrivate);
682  skip.insert(APIPermission::kChromeosInfoPrivate);
683  skip.insert(APIPermission::kCloudPrintPrivate);
684  skip.insert(APIPermission::kCommandLinePrivate);
685  skip.insert(APIPermission::kDeveloperPrivate);
686  skip.insert(APIPermission::kDial);
687  skip.insert(APIPermission::kDownloadsInternal);
688  skip.insert(APIPermission::kEchoPrivate);
689  skip.insert(APIPermission::kEnterprisePlatformKeysPrivate);
690  skip.insert(APIPermission::kFileBrowserHandlerInternal);
691  skip.insert(APIPermission::kFileBrowserPrivate);
692  skip.insert(APIPermission::kIdentityPrivate);
693  skip.insert(APIPermission::kInputMethodPrivate);
694  skip.insert(APIPermission::kManagedModePrivate);
695  skip.insert(APIPermission::kMediaGalleriesPrivate);
696  skip.insert(APIPermission::kMediaPlayerPrivate);
697  skip.insert(APIPermission::kMetricsPrivate);
698  skip.insert(APIPermission::kNetworkingPrivate);
699  skip.insert(APIPermission::kRtcPrivate);
700  skip.insert(APIPermission::kStreamsPrivate);
701  skip.insert(APIPermission::kSystemPrivate);
702  skip.insert(APIPermission::kTerminalPrivate);
703  skip.insert(APIPermission::kWallpaperPrivate);
704  skip.insert(APIPermission::kWebRequestInternal);
705  skip.insert(APIPermission::kWebSocketProxyPrivate);
706  skip.insert(APIPermission::kWebstorePrivate);
707
708  // Warned as part of host permissions.
709  skip.insert(APIPermission::kDevtools);
710
711  // Platform apps.
712  skip.insert(APIPermission::kFileSystem);
713  skip.insert(APIPermission::kFileSystemRetainFiles);
714  skip.insert(APIPermission::kSocket);
715  skip.insert(APIPermission::kUsbDevice);
716
717  PermissionsInfo* info = PermissionsInfo::GetInstance();
718  APIPermissionSet permissions = info->GetAll();
719  for (APIPermissionSet::const_iterator i = permissions.begin();
720       i != permissions.end(); ++i) {
721    const APIPermissionInfo* permission_info = i->info();
722    EXPECT_TRUE(permission_info != NULL);
723
724    // Always skip permissions that cannot be in the manifest.
725    scoped_ptr<const APIPermission> permission(
726        permission_info->CreateAPIPermission());
727    if (permission->ManifestEntryForbidden())
728      continue;
729
730    if (skip.count(i->id())) {
731      EXPECT_EQ(PermissionMessage::kNone, permission_info->message_id())
732          << "unexpected message_id for " << permission_info->name();
733    } else {
734      EXPECT_NE(PermissionMessage::kNone, permission_info->message_id())
735          << "missing message_id for " << permission_info->name();
736    }
737  }
738}
739
740// Tests the default permissions (empty API permission set).
741TEST(PermissionsTest, DefaultFunctionAccess) {
742  const struct {
743    const char* permission_name;
744    bool expect_success;
745  } kTests[] = {
746    // Negative test.
747    { "non_existing_permission", false },
748    // Test default module/package permission.
749    { "browserAction",  true },
750    { "devtools",       true },
751    { "extension",      true },
752    { "i18n",           true },
753    { "pageAction",     true },
754    { "pageActions",    true },
755    { "test",           true },
756    // Some negative tests.
757    { "bookmarks",      false },
758    { "cookies",        false },
759    { "history",        false },
760    // Make sure we find the module name after stripping '.' and '/'.
761    { "browserAction/abcd/onClick",  true },
762    { "browserAction.abcd.onClick",  true },
763    // Test Tabs functions.
764    { "tabs.create",      true},
765    { "tabs.duplicate",   true},
766    { "tabs.update",      true},
767    { "tabs.getSelected", true},
768    { "tabs.onUpdated",   true },
769  };
770
771  scoped_refptr<PermissionSet> empty = new PermissionSet();
772  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) {
773    EXPECT_EQ(kTests[i].expect_success,
774              empty->HasAccessToFunction(kTests[i].permission_name, true))
775                  << "Permission being tested: " << kTests[i].permission_name;
776  }
777}
778
779// Tests the default permissions (empty API permission set).
780TEST(PermissionsTest, DefaultAnyAPIAccess) {
781  const struct {
782    const char* api_name;
783    bool expect_success;
784  } kTests[] = {
785    // Negative test.
786    { "non_existing_permission", false },
787    // Test default module/package permission.
788    { "browserAction",  true },
789    { "devtools",       true },
790    { "extension",      true },
791    { "i18n",           true },
792    { "pageAction",     true },
793    { "pageActions",    true },
794    { "test",           true },
795    // Some negative tests.
796    { "bookmarks",      false },
797    { "cookies",        false },
798    { "history",        false },
799    // Negative APIs that have positive individual functions.
800    { "management",     true},
801    { "tabs",           true},
802  };
803
804  scoped_refptr<PermissionSet> empty = new PermissionSet();
805  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) {
806    EXPECT_EQ(kTests[i].expect_success,
807              empty->HasAnyAccessToAPI(kTests[i].api_name));
808  }
809}
810
811TEST(PermissionsTest, GetWarningMessages_ManyHosts) {
812  scoped_refptr<Extension> extension;
813
814  extension = LoadManifest("permissions", "many-hosts.json");
815  std::vector<string16> warnings =
816      PermissionsData::GetPermissionMessageStrings(extension);
817  ASSERT_EQ(1u, warnings.size());
818  EXPECT_EQ("Access your data on encrypted.google.com and www.google.com",
819            UTF16ToUTF8(warnings[0]));
820}
821
822TEST(PermissionsTest, GetWarningMessages_Plugins) {
823  scoped_refptr<Extension> extension;
824  scoped_refptr<PermissionSet> permissions;
825
826  extension = LoadManifest("permissions", "plugins.json");
827  std::vector<string16> warnings =
828      PermissionsData::GetPermissionMessageStrings(extension);
829  // We don't parse the plugins key on Chrome OS, so it should not ask for any
830  // permissions.
831#if defined(OS_CHROMEOS)
832  ASSERT_EQ(0u, warnings.size());
833#else
834  ASSERT_EQ(1u, warnings.size());
835  EXPECT_EQ("Access all data on your computer and the websites you visit",
836            UTF16ToUTF8(warnings[0]));
837#endif
838}
839
840TEST(PermissionsTest, GetWarningMessages_AudioVideo) {
841  // Both audio and video present.
842  scoped_refptr<Extension> extension =
843      LoadManifest("permissions", "audio-video.json");
844  PermissionSet* set =
845      const_cast<PermissionSet*>(
846          extension->GetActivePermissions().get());
847  std::vector<string16> warnings =
848      set->GetWarningMessages(extension->GetType());
849  EXPECT_FALSE(Contains(warnings, "Use your microphone"));
850  EXPECT_FALSE(Contains(warnings, "Use your camera"));
851  EXPECT_TRUE(Contains(warnings, "Use your microphone and camera"));
852  size_t combined_index = IndexOf(warnings, "Use your microphone and camera");
853  size_t combined_size = warnings.size();
854
855  // Just audio present.
856  set->apis_.erase(APIPermission::kVideoCapture);
857  warnings = set->GetWarningMessages(extension->GetType());
858  EXPECT_EQ(combined_size, warnings.size());
859  EXPECT_EQ(combined_index, IndexOf(warnings, "Use your microphone"));
860  EXPECT_FALSE(Contains(warnings, "Use your camera"));
861  EXPECT_FALSE(Contains(warnings, "Use your microphone and camera"));
862
863  // Just video present.
864  set->apis_.erase(APIPermission::kAudioCapture);
865  set->apis_.insert(APIPermission::kVideoCapture);
866  warnings = set->GetWarningMessages(extension->GetType());
867  EXPECT_EQ(combined_size, warnings.size());
868  EXPECT_FALSE(Contains(warnings, "Use your microphone"));
869  EXPECT_FALSE(Contains(warnings, "Use your microphone and camera"));
870  EXPECT_TRUE(Contains(warnings, "Use your camera"));
871}
872
873TEST(PermissionsTest, GetWarningMessages_Serial) {
874  scoped_refptr<Extension> extension =
875      LoadManifest("permissions", "serial.json");
876
877  EXPECT_TRUE(extension->is_platform_app());
878  EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSerial));
879  std::vector<string16> warnings =
880      PermissionsData::GetPermissionMessageStrings(extension);
881  EXPECT_TRUE(Contains(warnings,
882                       "Use serial devices attached to your computer"));
883  ASSERT_EQ(1u, warnings.size());
884}
885
886TEST(PermissionsTest, GetWarningMessages_Socket_AnyHost) {
887  Feature::ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
888
889  scoped_refptr<Extension> extension =
890      LoadManifest("permissions", "socket_any_host.json");
891  EXPECT_TRUE(extension->is_platform_app());
892  EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSocket));
893  std::vector<string16> warnings =
894      PermissionsData::GetPermissionMessageStrings(extension);
895  EXPECT_EQ(1u, warnings.size());
896  EXPECT_TRUE(Contains(warnings, "Exchange data with any computer "
897                                 "on the local network or internet"));
898}
899
900TEST(PermissionsTest, GetWarningMessages_Socket_OneDomainTwoHostnames) {
901  Feature::ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
902
903  scoped_refptr<Extension> extension =
904      LoadManifest("permissions", "socket_one_domain_two_hostnames.json");
905  EXPECT_TRUE(extension->is_platform_app());
906  EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSocket));
907  std::vector<string16> warnings =
908      PermissionsData::GetPermissionMessageStrings(extension);
909
910  // Verify the warnings, including support for unicode characters, the fact
911  // that domain host warnings come before specific host warnings, and the fact
912  // that domains and hostnames are in alphabetical order regardless of the
913  // order in the manifest file.
914  EXPECT_EQ(2u, warnings.size());
915  if (warnings.size() > 0)
916    EXPECT_EQ(warnings[0],
917              UTF8ToUTF16("Exchange data with any computer in the domain "
918                          "example.org"));
919  if (warnings.size() > 1)
920    EXPECT_EQ(warnings[1],
921              UTF8ToUTF16("Exchange data with the computers named: "
922                          "b\xC3\xA5r.example.com foo.example.com"));
923                          // "\xC3\xA5" = UTF-8 for lowercase A with ring above
924}
925
926TEST(PermissionsTest, GetWarningMessages_Socket_TwoDomainsOneHostname) {
927  Feature::ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
928
929  scoped_refptr<Extension> extension =
930      LoadManifest("permissions", "socket_two_domains_one_hostname.json");
931  EXPECT_TRUE(extension->is_platform_app());
932  EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSocket));
933  std::vector<string16> warnings =
934      PermissionsData::GetPermissionMessageStrings(extension);
935
936  // Verify the warnings, including the fact that domain host warnings come
937  // before specific host warnings and the fact that domains and hostnames are
938  // in alphabetical order regardless of the order in the manifest file.
939  EXPECT_EQ(2u, warnings.size());
940  if (warnings.size() > 0)
941    EXPECT_EQ(warnings[0],
942              UTF8ToUTF16("Exchange data with any computer in the domains: "
943                           "example.com foo.example.org"));
944  if (warnings.size() > 1)
945    EXPECT_EQ(warnings[1],
946              UTF8ToUTF16("Exchange data with the computer named "
947                           "bar.example.org"));
948}
949
950TEST(PermissionsTest, GetWarningMessages_PlatformApppHosts) {
951  scoped_refptr<Extension> extension;
952
953  extension = LoadManifest("permissions", "platform_app_hosts.json");
954  EXPECT_TRUE(extension->is_platform_app());
955  std::vector<string16> warnings =
956      PermissionsData::GetPermissionMessageStrings(extension);
957  ASSERT_EQ(0u, warnings.size());
958
959  extension = LoadManifest("permissions", "platform_app_all_urls.json");
960  EXPECT_TRUE(extension->is_platform_app());
961  warnings = PermissionsData::GetPermissionMessageStrings(extension);
962  ASSERT_EQ(0u, warnings.size());
963}
964
965TEST(PermissionsTest, GetDistinctHostsForDisplay) {
966  scoped_refptr<PermissionSet> perm_set;
967  APIPermissionSet empty_perms;
968  std::set<std::string> expected;
969  expected.insert("www.foo.com");
970  expected.insert("www.bar.com");
971  expected.insert("www.baz.com");
972  URLPatternSet explicit_hosts;
973  URLPatternSet scriptable_hosts;
974
975  {
976    SCOPED_TRACE("no dupes");
977
978    // Simple list with no dupes.
979    explicit_hosts.AddPattern(
980        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com/path"));
981    explicit_hosts.AddPattern(
982        URLPattern(URLPattern::SCHEME_HTTP, "http://www.bar.com/path"));
983    explicit_hosts.AddPattern(
984        URLPattern(URLPattern::SCHEME_HTTP, "http://www.baz.com/path"));
985    perm_set = new PermissionSet(
986        empty_perms, explicit_hosts, scriptable_hosts);
987    EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
988  }
989
990  {
991    SCOPED_TRACE("two dupes");
992
993    // Add some dupes.
994    explicit_hosts.AddPattern(
995        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com/path"));
996    explicit_hosts.AddPattern(
997        URLPattern(URLPattern::SCHEME_HTTP, "http://www.baz.com/path"));
998    perm_set = new PermissionSet(
999        empty_perms, explicit_hosts, scriptable_hosts);
1000    EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
1001  }
1002
1003  {
1004    SCOPED_TRACE("schemes differ");
1005
1006    // Add a pattern that differs only by scheme. This should be filtered out.
1007    explicit_hosts.AddPattern(
1008        URLPattern(URLPattern::SCHEME_HTTPS, "https://www.bar.com/path"));
1009    perm_set = new PermissionSet(
1010        empty_perms, explicit_hosts, scriptable_hosts);
1011    EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
1012  }
1013
1014  {
1015    SCOPED_TRACE("paths differ");
1016
1017    // Add some dupes by path.
1018    explicit_hosts.AddPattern(
1019        URLPattern(URLPattern::SCHEME_HTTP, "http://www.bar.com/pathypath"));
1020    perm_set = new PermissionSet(
1021        empty_perms, explicit_hosts, scriptable_hosts);
1022    EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
1023  }
1024
1025  {
1026    SCOPED_TRACE("subdomains differ");
1027
1028    // We don't do anything special for subdomains.
1029    explicit_hosts.AddPattern(
1030        URLPattern(URLPattern::SCHEME_HTTP, "http://monkey.www.bar.com/path"));
1031    explicit_hosts.AddPattern(
1032        URLPattern(URLPattern::SCHEME_HTTP, "http://bar.com/path"));
1033
1034    expected.insert("monkey.www.bar.com");
1035    expected.insert("bar.com");
1036
1037    perm_set = new PermissionSet(
1038        empty_perms, explicit_hosts, scriptable_hosts);
1039    EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
1040  }
1041
1042  {
1043    SCOPED_TRACE("RCDs differ");
1044
1045    // Now test for RCD uniquing.
1046    explicit_hosts.AddPattern(
1047        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com/path"));
1048    explicit_hosts.AddPattern(
1049        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path"));
1050    explicit_hosts.AddPattern(
1051        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.de/path"));
1052    explicit_hosts.AddPattern(
1053        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca.us/path"));
1054    explicit_hosts.AddPattern(
1055        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.net/path"));
1056    explicit_hosts.AddPattern(
1057        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com.my/path"));
1058
1059    // This is an unknown RCD, which shouldn't be uniqued out.
1060    explicit_hosts.AddPattern(
1061        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.xyzzy/path"));
1062    // But it should only occur once.
1063    explicit_hosts.AddPattern(
1064        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.xyzzy/path"));
1065
1066    expected.insert("www.foo.xyzzy");
1067
1068    perm_set = new PermissionSet(
1069        empty_perms, explicit_hosts, scriptable_hosts);
1070    EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
1071  }
1072
1073  {
1074    SCOPED_TRACE("wildcards");
1075
1076    explicit_hosts.AddPattern(
1077        URLPattern(URLPattern::SCHEME_HTTP, "http://*.google.com/*"));
1078
1079    expected.insert("*.google.com");
1080
1081    perm_set = new PermissionSet(
1082        empty_perms, explicit_hosts, scriptable_hosts);
1083    EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
1084  }
1085
1086  {
1087    SCOPED_TRACE("scriptable hosts");
1088    explicit_hosts.ClearPatterns();
1089    scriptable_hosts.ClearPatterns();
1090    expected.clear();
1091
1092    explicit_hosts.AddPattern(
1093        URLPattern(URLPattern::SCHEME_HTTP, "http://*.google.com/*"));
1094    scriptable_hosts.AddPattern(
1095        URLPattern(URLPattern::SCHEME_HTTP, "http://*.example.com/*"));
1096
1097    expected.insert("*.google.com");
1098    expected.insert("*.example.com");
1099
1100    perm_set = new PermissionSet(
1101        empty_perms, explicit_hosts, scriptable_hosts);
1102    EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
1103  }
1104
1105  {
1106    // We don't display warnings for file URLs because they are off by default.
1107    SCOPED_TRACE("file urls");
1108    explicit_hosts.ClearPatterns();
1109    scriptable_hosts.ClearPatterns();
1110    expected.clear();
1111
1112    explicit_hosts.AddPattern(
1113        URLPattern(URLPattern::SCHEME_FILE, "file:///*"));
1114
1115    perm_set = new PermissionSet(
1116        empty_perms, explicit_hosts, scriptable_hosts);
1117    EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
1118  }
1119}
1120
1121TEST(PermissionsTest, GetDistinctHostsForDisplay_ComIsBestRcd) {
1122  scoped_refptr<PermissionSet> perm_set;
1123  APIPermissionSet empty_perms;
1124  URLPatternSet explicit_hosts;
1125  URLPatternSet scriptable_hosts;
1126  explicit_hosts.AddPattern(
1127      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca/path"));
1128  explicit_hosts.AddPattern(
1129      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.org/path"));
1130  explicit_hosts.AddPattern(
1131      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path"));
1132  explicit_hosts.AddPattern(
1133      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.net/path"));
1134  explicit_hosts.AddPattern(
1135      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.jp/path"));
1136  explicit_hosts.AddPattern(
1137      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com/path"));
1138
1139  std::set<std::string> expected;
1140  expected.insert("www.foo.com");
1141  perm_set = new PermissionSet(
1142      empty_perms, explicit_hosts, scriptable_hosts);
1143  EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
1144}
1145
1146TEST(PermissionsTest, GetDistinctHostsForDisplay_NetIs2ndBestRcd) {
1147  scoped_refptr<PermissionSet> perm_set;
1148  APIPermissionSet empty_perms;
1149  URLPatternSet explicit_hosts;
1150  URLPatternSet scriptable_hosts;
1151  explicit_hosts.AddPattern(
1152      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca/path"));
1153  explicit_hosts.AddPattern(
1154      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.org/path"));
1155  explicit_hosts.AddPattern(
1156      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path"));
1157  explicit_hosts.AddPattern(
1158      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.net/path"));
1159  explicit_hosts.AddPattern(
1160      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.jp/path"));
1161  // No http://www.foo.com/path
1162
1163  std::set<std::string> expected;
1164  expected.insert("www.foo.net");
1165  perm_set = new PermissionSet(
1166      empty_perms, explicit_hosts, scriptable_hosts);
1167  EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
1168}
1169
1170TEST(PermissionsTest,
1171     GetDistinctHostsForDisplay_OrgIs3rdBestRcd) {
1172  scoped_refptr<PermissionSet> perm_set;
1173  APIPermissionSet empty_perms;
1174  URLPatternSet explicit_hosts;
1175  URLPatternSet scriptable_hosts;
1176  explicit_hosts.AddPattern(
1177      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca/path"));
1178  explicit_hosts.AddPattern(
1179      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.org/path"));
1180  explicit_hosts.AddPattern(
1181      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path"));
1182  // No http://www.foo.net/path
1183  explicit_hosts.AddPattern(
1184      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.jp/path"));
1185  // No http://www.foo.com/path
1186
1187  std::set<std::string> expected;
1188  expected.insert("www.foo.org");
1189  perm_set = new PermissionSet(
1190      empty_perms, explicit_hosts, scriptable_hosts);
1191  EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
1192}
1193
1194TEST(PermissionsTest,
1195     GetDistinctHostsForDisplay_FirstInListIs4thBestRcd) {
1196  scoped_refptr<PermissionSet> perm_set;
1197  APIPermissionSet empty_perms;
1198  URLPatternSet explicit_hosts;
1199  URLPatternSet scriptable_hosts;
1200  explicit_hosts.AddPattern(
1201      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca/path"));
1202  // No http://www.foo.org/path
1203  explicit_hosts.AddPattern(
1204      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path"));
1205  // No http://www.foo.net/path
1206  explicit_hosts.AddPattern(
1207      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.jp/path"));
1208  // No http://www.foo.com/path
1209
1210  std::set<std::string> expected;
1211  expected.insert("www.foo.ca");
1212  perm_set = new PermissionSet(
1213      empty_perms, explicit_hosts, scriptable_hosts);
1214  EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
1215}
1216
1217TEST(PermissionsTest, HasLessHostPrivilegesThan) {
1218  URLPatternSet elist1;
1219  URLPatternSet elist2;
1220  URLPatternSet slist1;
1221  URLPatternSet slist2;
1222  scoped_refptr<PermissionSet> set1;
1223  scoped_refptr<PermissionSet> set2;
1224  APIPermissionSet empty_perms;
1225  elist1.AddPattern(
1226      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com.hk/path"));
1227  elist1.AddPattern(
1228      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/path"));
1229
1230  // Test that the host order does not matter.
1231  elist2.AddPattern(
1232      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/path"));
1233  elist2.AddPattern(
1234      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com.hk/path"));
1235
1236  set1 = new PermissionSet(empty_perms, elist1, slist1);
1237  set2 = new PermissionSet(empty_perms, elist2, slist2);
1238
1239  EXPECT_FALSE(set1->HasLessHostPrivilegesThan(set2.get()));
1240  EXPECT_FALSE(set2->HasLessHostPrivilegesThan(set1.get()));
1241
1242  // Test that paths are ignored.
1243  elist2.ClearPatterns();
1244  elist2.AddPattern(
1245      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/*"));
1246  set2 = new PermissionSet(empty_perms, elist2, slist2);
1247  EXPECT_FALSE(set1->HasLessHostPrivilegesThan(set2.get()));
1248  EXPECT_FALSE(set2->HasLessHostPrivilegesThan(set1.get()));
1249
1250  // Test that RCDs are ignored.
1251  elist2.ClearPatterns();
1252  elist2.AddPattern(
1253      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com.hk/*"));
1254  set2 = new PermissionSet(empty_perms, elist2, slist2);
1255  EXPECT_FALSE(set1->HasLessHostPrivilegesThan(set2.get()));
1256  EXPECT_FALSE(set2->HasLessHostPrivilegesThan(set1.get()));
1257
1258  // Test that subdomain wildcards are handled properly.
1259  elist2.ClearPatterns();
1260  elist2.AddPattern(
1261      URLPattern(URLPattern::SCHEME_HTTP, "http://*.google.com.hk/*"));
1262  set2 = new PermissionSet(empty_perms, elist2, slist2);
1263  EXPECT_TRUE(set1->HasLessHostPrivilegesThan(set2.get()));
1264  // TODO(jstritar): Does not match subdomains properly. http://crbug.com/65337
1265  // EXPECT_FALSE(set2->HasLessHostPrivilegesThan(set1.get()));
1266
1267  // Test that different domains count as different hosts.
1268  elist2.ClearPatterns();
1269  elist2.AddPattern(
1270      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/path"));
1271  elist2.AddPattern(
1272      URLPattern(URLPattern::SCHEME_HTTP, "http://www.example.org/path"));
1273  set2 = new PermissionSet(empty_perms, elist2, slist2);
1274  EXPECT_TRUE(set1->HasLessHostPrivilegesThan(set2.get()));
1275  EXPECT_FALSE(set2->HasLessHostPrivilegesThan(set1.get()));
1276
1277  // Test that different subdomains count as different hosts.
1278  elist2.ClearPatterns();
1279  elist2.AddPattern(
1280      URLPattern(URLPattern::SCHEME_HTTP, "http://mail.google.com/*"));
1281  set2 = new PermissionSet(empty_perms, elist2, slist2);
1282  EXPECT_TRUE(set1->HasLessHostPrivilegesThan(set2.get()));
1283  EXPECT_TRUE(set2->HasLessHostPrivilegesThan(set1.get()));
1284}
1285
1286TEST(PermissionsTest, GetAPIsAsStrings) {
1287  APIPermissionSet apis;
1288  URLPatternSet empty_set;
1289
1290  apis.insert(APIPermission::kProxy);
1291  apis.insert(APIPermission::kBackground);
1292  apis.insert(APIPermission::kNotification);
1293  apis.insert(APIPermission::kTab);
1294
1295  scoped_refptr<PermissionSet> perm_set = new PermissionSet(
1296      apis, empty_set, empty_set);
1297  std::set<std::string> api_names = perm_set->GetAPIsAsStrings();
1298
1299  // The result is correct if it has the same number of elements
1300  // and we can convert it back to the id set.
1301  EXPECT_EQ(4u, api_names.size());
1302  EXPECT_EQ(apis,
1303            PermissionsInfo::GetInstance()->GetAllByName(api_names));
1304}
1305
1306TEST(PermissionsTest, IsEmpty) {
1307  APIPermissionSet empty_apis;
1308  URLPatternSet empty_extent;
1309
1310  scoped_refptr<PermissionSet> empty = new PermissionSet();
1311  EXPECT_TRUE(empty->IsEmpty());
1312  scoped_refptr<PermissionSet> perm_set;
1313
1314  perm_set = new PermissionSet(empty_apis, empty_extent, empty_extent);
1315  EXPECT_TRUE(perm_set->IsEmpty());
1316
1317  APIPermissionSet non_empty_apis;
1318  non_empty_apis.insert(APIPermission::kBackground);
1319  perm_set = new PermissionSet(
1320      non_empty_apis, empty_extent, empty_extent);
1321  EXPECT_FALSE(perm_set->IsEmpty());
1322
1323  // Try non standard host
1324  URLPatternSet non_empty_extent;
1325  AddPattern(&non_empty_extent, "http://www.google.com/*");
1326
1327  perm_set = new PermissionSet(
1328      empty_apis, non_empty_extent, empty_extent);
1329  EXPECT_FALSE(perm_set->IsEmpty());
1330
1331  perm_set = new PermissionSet(
1332      empty_apis, empty_extent, non_empty_extent);
1333  EXPECT_FALSE(perm_set->IsEmpty());
1334}
1335
1336TEST(PermissionsTest, ImpliedPermissions) {
1337  URLPatternSet empty_extent;
1338  APIPermissionSet apis;
1339  apis.insert(APIPermission::kWebRequest);
1340  apis.insert(APIPermission::kFileBrowserHandler);
1341  EXPECT_EQ(2U, apis.size());
1342
1343  scoped_refptr<PermissionSet> perm_set;
1344  perm_set = new PermissionSet(apis, empty_extent, empty_extent);
1345  EXPECT_EQ(4U, perm_set->apis().size());
1346}
1347
1348TEST(PermissionsTest, SyncFileSystemPermission) {
1349  scoped_refptr<Extension> extension = LoadManifest(
1350      "permissions", "sync_file_system.json");
1351  APIPermissionSet apis;
1352  apis.insert(APIPermission::kSyncFileSystem);
1353  EXPECT_TRUE(extension->is_platform_app());
1354  EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSyncFileSystem));
1355  std::vector<string16> warnings =
1356      PermissionsData::GetPermissionMessageStrings(extension);
1357  EXPECT_TRUE(Contains(warnings, "Store data in your Google Drive account"));
1358  ASSERT_EQ(1u, warnings.size());
1359}
1360
1361}  // namespace extensions
1362