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