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