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