permission_set_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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::kPointerLock);
657  skip.insert(APIPermission::kPower);
658  skip.insert(APIPermission::kPushMessaging);
659  skip.insert(APIPermission::kSessions);
660  skip.insert(APIPermission::kStorage);
661  skip.insert(APIPermission::kSystemCpu);
662  skip.insert(APIPermission::kSystemDisplay);
663  skip.insert(APIPermission::kSystemMemory);
664  skip.insert(APIPermission::kSystemNetwork);
665  skip.insert(APIPermission::kSystemStorage);
666  skip.insert(APIPermission::kTts);
667  skip.insert(APIPermission::kUnlimitedStorage);
668  skip.insert(APIPermission::kWebView);
669  skip.insert(APIPermission::kOverrideEscFullscreen);
670
671  // TODO(erikkay) add a string for this permission.
672  skip.insert(APIPermission::kBackground);
673
674  skip.insert(APIPermission::kClipboardWrite);
675
676  // The cookie permission does nothing unless you have associated host
677  // permissions.
678  skip.insert(APIPermission::kCookie);
679
680  // These are warned as part of host permission checks.
681  skip.insert(APIPermission::kDeclarativeContent);
682  skip.insert(APIPermission::kPageCapture);
683  skip.insert(APIPermission::kProxy);
684  skip.insert(APIPermission::kTabCapture);
685  skip.insert(APIPermission::kWebRequest);
686  skip.insert(APIPermission::kWebRequestBlocking);
687
688  // This permission requires explicit user action (context menu handler)
689  // so we won't prompt for it for now.
690  skip.insert(APIPermission::kFileBrowserHandler);
691
692  // These permissions require explicit user action (configuration dialog)
693  // so we don't prompt for them at install time.
694  skip.insert(APIPermission::kMediaGalleries);
695
696  // If you've turned on the experimental command-line flag, we don't need
697  // to warn you further.
698  skip.insert(APIPermission::kExperimental);
699
700  // The Identity API has its own server-driven permission prompts.
701  skip.insert(APIPermission::kIdentity);
702
703  // These are private.
704  skip.insert(APIPermission::kAutoTestPrivate);
705  skip.insert(APIPermission::kBookmarkManagerPrivate);
706  skip.insert(APIPermission::kBrailleDisplayPrivate);
707  skip.insert(APIPermission::kCast);
708  skip.insert(APIPermission::kCastStreaming);
709  skip.insert(APIPermission::kChromeosInfoPrivate);
710  skip.insert(APIPermission::kCloudPrintPrivate);
711  skip.insert(APIPermission::kCommandLinePrivate);
712  skip.insert(APIPermission::kDeveloperPrivate);
713  skip.insert(APIPermission::kDial);
714  skip.insert(APIPermission::kDownloadsInternal);
715  skip.insert(APIPermission::kEchoPrivate);
716  skip.insert(APIPermission::kEnterprisePlatformKeysPrivate);
717  skip.insert(APIPermission::kFeedbackPrivate);
718  skip.insert(APIPermission::kFileBrowserHandlerInternal);
719  skip.insert(APIPermission::kFileBrowserPrivate);
720  skip.insert(APIPermission::kFirstRunPrivate);
721  skip.insert(APIPermission::kHotwordPrivate);
722  skip.insert(APIPermission::kIdentityPrivate);
723  skip.insert(APIPermission::kInfobars);
724  skip.insert(APIPermission::kInputMethodPrivate);
725  skip.insert(APIPermission::kMediaGalleriesPrivate);
726  skip.insert(APIPermission::kMediaPlayerPrivate);
727  skip.insert(APIPermission::kMetricsPrivate);
728  skip.insert(APIPermission::kMDns);
729  skip.insert(APIPermission::kPreferencesPrivate);
730  skip.insert(APIPermission::kPrincipalsPrivate);
731  skip.insert(APIPermission::kImageWriterPrivate);
732  skip.insert(APIPermission::kReadingListPrivate);
733  skip.insert(APIPermission::kRtcPrivate);
734  skip.insert(APIPermission::kStreamsPrivate);
735  skip.insert(APIPermission::kSystemPrivate);
736  skip.insert(APIPermission::kTabCaptureForTab);
737  skip.insert(APIPermission::kTerminalPrivate);
738  skip.insert(APIPermission::kVirtualKeyboardPrivate);
739  skip.insert(APIPermission::kWallpaperPrivate);
740  skip.insert(APIPermission::kWebRequestInternal);
741  skip.insert(APIPermission::kWebrtcAudioPrivate);
742  skip.insert(APIPermission::kWebrtcLoggingPrivate);
743  skip.insert(APIPermission::kWebstorePrivate);
744
745  // Warned as part of host permissions.
746  skip.insert(APIPermission::kDevtools);
747
748  // Platform apps.
749  skip.insert(APIPermission::kFileSystem);
750  skip.insert(APIPermission::kFileSystemProvider);
751  skip.insert(APIPermission::kFileSystemRetainEntries);
752  skip.insert(APIPermission::kSocket);
753  skip.insert(APIPermission::kUsbDevice);
754
755  PermissionsInfo* info = PermissionsInfo::GetInstance();
756  APIPermissionSet permissions = info->GetAll();
757  for (APIPermissionSet::const_iterator i = permissions.begin();
758       i != permissions.end(); ++i) {
759    const APIPermissionInfo* permission_info = i->info();
760    EXPECT_TRUE(permission_info != NULL);
761
762    if (skip.count(i->id())) {
763      EXPECT_EQ(PermissionMessage::kNone, permission_info->message_id())
764          << "unexpected message_id for " << permission_info->name();
765    } else {
766      EXPECT_NE(PermissionMessage::kNone, permission_info->message_id())
767          << "missing message_id for " << permission_info->name();
768    }
769  }
770}
771
772TEST(PermissionsTest, FileSystemPermissionMessages) {
773  APIPermissionSet api_permissions;
774  api_permissions.insert(APIPermission::kFileSystemWrite);
775  api_permissions.insert(APIPermission::kFileSystemDirectory);
776  scoped_refptr<PermissionSet> permissions(
777      new PermissionSet(api_permissions, ManifestPermissionSet(),
778                        URLPatternSet(), URLPatternSet()));
779  PermissionMessages messages =
780      PermissionMessageProvider::Get()->GetPermissionMessages(
781          permissions, Manifest::TYPE_PLATFORM_APP);
782  ASSERT_EQ(2u, messages.size());
783  std::sort(messages.begin(), messages.end());
784  std::set<PermissionMessage::ID> ids;
785  for (PermissionMessages::const_iterator it = messages.begin();
786       it != messages.end(); ++it) {
787    ids.insert(it->id());
788  }
789  EXPECT_TRUE(ContainsKey(ids, PermissionMessage::kFileSystemDirectory));
790  EXPECT_TRUE(ContainsKey(ids, PermissionMessage::kFileSystemWrite));
791}
792
793TEST(PermissionsTest, HiddenFileSystemPermissionMessages) {
794  APIPermissionSet api_permissions;
795  api_permissions.insert(APIPermission::kFileSystemWrite);
796  api_permissions.insert(APIPermission::kFileSystemDirectory);
797  api_permissions.insert(APIPermission::kFileSystemWriteDirectory);
798  scoped_refptr<PermissionSet> permissions(
799      new PermissionSet(api_permissions, ManifestPermissionSet(),
800                        URLPatternSet(), URLPatternSet()));
801  PermissionMessages messages =
802      PermissionMessageProvider::Get()->GetPermissionMessages(
803          permissions, Manifest::TYPE_PLATFORM_APP);
804  ASSERT_EQ(1u, messages.size());
805  EXPECT_EQ(PermissionMessage::kFileSystemWriteDirectory, messages[0].id());
806}
807
808TEST(PermissionsTest, MergedFileSystemPermissionComparison) {
809  APIPermissionSet write_api_permissions;
810  write_api_permissions.insert(APIPermission::kFileSystemWrite);
811  scoped_refptr<PermissionSet> write_permissions(
812      new PermissionSet(write_api_permissions, ManifestPermissionSet(),
813                        URLPatternSet(), URLPatternSet()));
814
815  APIPermissionSet directory_api_permissions;
816  directory_api_permissions.insert(APIPermission::kFileSystemDirectory);
817  scoped_refptr<PermissionSet> directory_permissions(
818      new PermissionSet(directory_api_permissions, ManifestPermissionSet(),
819                        URLPatternSet(), URLPatternSet()));
820
821  APIPermissionSet write_directory_api_permissions;
822  write_directory_api_permissions.insert(
823      APIPermission::kFileSystemWriteDirectory);
824  scoped_refptr<PermissionSet> write_directory_permissions(
825      new PermissionSet(write_directory_api_permissions,
826                        ManifestPermissionSet(),
827                        URLPatternSet(),
828                        URLPatternSet()));
829
830  const PermissionMessageProvider* provider = PermissionMessageProvider::Get();
831  EXPECT_FALSE(provider->IsPrivilegeIncrease(write_directory_permissions,
832                                             write_permissions,
833                                             Manifest::TYPE_PLATFORM_APP));
834  EXPECT_FALSE(provider->IsPrivilegeIncrease(write_directory_permissions,
835                                             directory_permissions,
836                                             Manifest::TYPE_PLATFORM_APP));
837  EXPECT_TRUE(provider->IsPrivilegeIncrease(write_permissions,
838                                            directory_permissions,
839                                            Manifest::TYPE_PLATFORM_APP));
840  EXPECT_TRUE(provider->IsPrivilegeIncrease(write_permissions,
841                                            write_directory_permissions,
842                                            Manifest::TYPE_PLATFORM_APP));
843  EXPECT_TRUE(provider->IsPrivilegeIncrease(directory_permissions,
844                                            write_permissions,
845                                            Manifest::TYPE_PLATFORM_APP));
846  EXPECT_TRUE(provider->IsPrivilegeIncrease(directory_permissions,
847                                            write_directory_permissions,
848                                            Manifest::TYPE_PLATFORM_APP));
849}
850
851TEST(PermissionsTest, GetWarningMessages_ManyHosts) {
852  scoped_refptr<Extension> extension;
853
854  extension = LoadManifest("permissions", "many-hosts.json");
855  std::vector<base::string16> warnings =
856      PermissionsData::GetPermissionMessageStrings(extension.get());
857  ASSERT_EQ(1u, warnings.size());
858  EXPECT_EQ("Access your data on encrypted.google.com and www.google.com",
859            base::UTF16ToUTF8(warnings[0]));
860}
861
862TEST(PermissionsTest, GetWarningMessages_Plugins) {
863  scoped_refptr<Extension> extension;
864  scoped_refptr<PermissionSet> permissions;
865
866  extension = LoadManifest("permissions", "plugins.json");
867  std::vector<base::string16> warnings =
868      PermissionsData::GetPermissionMessageStrings(extension.get());
869// We don't parse the plugins key on Chrome OS, so it should not ask for any
870  // permissions.
871#if defined(OS_CHROMEOS)
872  ASSERT_EQ(0u, warnings.size());
873#else
874  ASSERT_EQ(1u, warnings.size());
875  EXPECT_EQ("Access all data on your computer and the websites you visit",
876            base::UTF16ToUTF8(warnings[0]));
877#endif
878}
879
880TEST(PermissionsTest, GetWarningMessages_AudioVideo) {
881  // Both audio and video present.
882  scoped_refptr<Extension> extension =
883      LoadManifest("permissions", "audio-video.json");
884  const PermissionMessageProvider* provider = PermissionMessageProvider::Get();
885  PermissionSet* set =
886      const_cast<PermissionSet*>(
887          extension->GetActivePermissions().get());
888  std::vector<base::string16> warnings =
889      provider->GetWarningMessages(set, extension->GetType());
890  EXPECT_FALSE(Contains(warnings, "Use your microphone"));
891  EXPECT_FALSE(Contains(warnings, "Use your camera"));
892  EXPECT_TRUE(Contains(warnings, "Use your microphone and camera"));
893  size_t combined_index = IndexOf(warnings, "Use your microphone and camera");
894  size_t combined_size = warnings.size();
895
896  // Just audio present.
897  set->apis_.erase(APIPermission::kVideoCapture);
898  warnings = provider->GetWarningMessages(set, extension->GetType());
899  EXPECT_EQ(combined_size, warnings.size());
900  EXPECT_EQ(combined_index, IndexOf(warnings, "Use your microphone"));
901  EXPECT_FALSE(Contains(warnings, "Use your camera"));
902  EXPECT_FALSE(Contains(warnings, "Use your microphone and camera"));
903
904  // Just video present.
905  set->apis_.erase(APIPermission::kAudioCapture);
906  set->apis_.insert(APIPermission::kVideoCapture);
907  warnings = provider->GetWarningMessages(set, extension->GetType());
908  EXPECT_EQ(combined_size, warnings.size());
909  EXPECT_FALSE(Contains(warnings, "Use your microphone"));
910  EXPECT_FALSE(Contains(warnings, "Use your microphone and camera"));
911  EXPECT_TRUE(Contains(warnings, "Use your camera"));
912}
913
914TEST(PermissionsTest, GetWarningMessages_DeclarativeWebRequest) {
915  // Test that if the declarativeWebRequest permission is present
916  // in combination with all hosts permission, then only the warning
917  // for host permissions is shown, because that covers the use of
918  // declarativeWebRequest.
919
920  // Until Declarative Web Request is in stable, let's make sure it is enabled
921  // on the current channel.
922  ScopedCurrentChannel sc(chrome::VersionInfo::CHANNEL_CANARY);
923
924  // First verify that declarativeWebRequest produces a message when host
925  // permissions do not cover all hosts.
926  scoped_refptr<Extension> extension =
927      LoadManifest("permissions", "web_request_com_host_permissions.json");
928  const PermissionMessageProvider* provider = PermissionMessageProvider::Get();
929  const PermissionSet* set = extension->GetActivePermissions().get();
930  std::vector<base::string16> warnings =
931      provider->GetWarningMessages(set, extension->GetType());
932  EXPECT_TRUE(Contains(warnings, "Block parts of web pages"));
933  EXPECT_FALSE(Contains(warnings, "Access your data on all websites"));
934
935  // Now verify that declarativeWebRequest does not produce a message when host
936  // permissions do cover all hosts.
937  extension =
938      LoadManifest("permissions", "web_request_all_host_permissions.json");
939  set = extension->GetActivePermissions().get();
940  warnings = provider->GetWarningMessages(set, extension->GetType());
941  EXPECT_FALSE(Contains(warnings, "Block parts of web pages"));
942  EXPECT_TRUE(Contains(warnings, "Access your data on all websites"));
943}
944
945TEST(PermissionsTest, GetWarningMessages_Serial) {
946  scoped_refptr<Extension> extension =
947      LoadManifest("permissions", "serial.json");
948
949  EXPECT_TRUE(extension->is_platform_app());
950  EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSerial));
951  std::vector<base::string16> warnings =
952      PermissionsData::GetPermissionMessageStrings(extension.get());
953  EXPECT_TRUE(
954      Contains(warnings, "Use serial devices attached to your computer"));
955  ASSERT_EQ(1u, warnings.size());
956}
957
958TEST(PermissionsTest, GetWarningMessages_Socket_AnyHost) {
959  ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
960
961  scoped_refptr<Extension> extension =
962      LoadManifest("permissions", "socket_any_host.json");
963  EXPECT_TRUE(extension->is_platform_app());
964  EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSocket));
965  std::vector<base::string16> warnings =
966      PermissionsData::GetPermissionMessageStrings(extension.get());
967  EXPECT_EQ(1u, warnings.size());
968  EXPECT_TRUE(Contains(warnings, "Exchange data with any computer "
969                                 "on the local network or internet"));
970}
971
972TEST(PermissionsTest, GetWarningMessages_Socket_OneDomainTwoHostnames) {
973  ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
974
975  scoped_refptr<Extension> extension =
976      LoadManifest("permissions", "socket_one_domain_two_hostnames.json");
977  EXPECT_TRUE(extension->is_platform_app());
978  EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSocket));
979  std::vector<base::string16> warnings =
980      PermissionsData::GetPermissionMessageStrings(extension.get());
981
982  // Verify the warnings, including support for unicode characters, the fact
983  // that domain host warnings come before specific host warnings, and the fact
984  // that domains and hostnames are in alphabetical order regardless of the
985  // order in the manifest file.
986  EXPECT_EQ(2u, warnings.size());
987  if (warnings.size() > 0)
988    EXPECT_EQ(warnings[0],
989              base::UTF8ToUTF16("Exchange data with any computer in the domain "
990                          "example.org"));
991  if (warnings.size() > 1)
992    EXPECT_EQ(warnings[1],
993              base::UTF8ToUTF16("Exchange data with the computers named: "
994                          "b\xC3\xA5r.example.com foo.example.com"));
995                          // "\xC3\xA5" = UTF-8 for lowercase A with ring above
996}
997
998TEST(PermissionsTest, GetWarningMessages_Socket_TwoDomainsOneHostname) {
999  ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
1000
1001  scoped_refptr<Extension> extension =
1002      LoadManifest("permissions", "socket_two_domains_one_hostname.json");
1003  EXPECT_TRUE(extension->is_platform_app());
1004  EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSocket));
1005  std::vector<base::string16> warnings =
1006      PermissionsData::GetPermissionMessageStrings(extension.get());
1007
1008  // Verify the warnings, including the fact that domain host warnings come
1009  // before specific host warnings and the fact that domains and hostnames are
1010  // in alphabetical order regardless of the order in the manifest file.
1011  EXPECT_EQ(2u, warnings.size());
1012  if (warnings.size() > 0)
1013    EXPECT_EQ(warnings[0],
1014              base::UTF8ToUTF16("Exchange data with any computer in the "
1015                                "domains: example.com foo.example.org"));
1016  if (warnings.size() > 1)
1017    EXPECT_EQ(warnings[1],
1018              base::UTF8ToUTF16("Exchange data with the computer named "
1019                                "bar.example.org"));
1020}
1021
1022TEST(PermissionsTest, GetWarningMessages_PlatformApppHosts) {
1023  scoped_refptr<Extension> extension;
1024
1025  extension = LoadManifest("permissions", "platform_app_hosts.json");
1026  EXPECT_TRUE(extension->is_platform_app());
1027  std::vector<base::string16> warnings =
1028      PermissionsData::GetPermissionMessageStrings(extension.get());
1029  ASSERT_EQ(0u, warnings.size());
1030
1031  extension = LoadManifest("permissions", "platform_app_all_urls.json");
1032  EXPECT_TRUE(extension->is_platform_app());
1033  warnings = PermissionsData::GetPermissionMessageStrings(extension.get());
1034  ASSERT_EQ(0u, warnings.size());
1035}
1036
1037TEST(PermissionsTest, GetDistinctHosts) {
1038  URLPatternSet explicit_hosts;
1039  std::set<std::string> expected;
1040  expected.insert("www.foo.com");
1041  expected.insert("www.bar.com");
1042  expected.insert("www.baz.com");
1043
1044  {
1045    SCOPED_TRACE("no dupes");
1046
1047    // Simple list with no dupes.
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.bar.com/path"));
1052    explicit_hosts.AddPattern(
1053        URLPattern(URLPattern::SCHEME_HTTP, "http://www.baz.com/path"));
1054    EXPECT_EQ(expected,
1055              permission_message_util::GetDistinctHosts(
1056                  explicit_hosts, true, true));
1057  }
1058
1059  {
1060    SCOPED_TRACE("two dupes");
1061
1062    // Add some dupes.
1063    explicit_hosts.AddPattern(
1064        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com/path"));
1065    explicit_hosts.AddPattern(
1066        URLPattern(URLPattern::SCHEME_HTTP, "http://www.baz.com/path"));
1067    EXPECT_EQ(expected,
1068              permission_message_util::GetDistinctHosts(
1069                  explicit_hosts, true, true));
1070  }
1071
1072  {
1073    SCOPED_TRACE("schemes differ");
1074
1075    // Add a pattern that differs only by scheme. This should be filtered out.
1076    explicit_hosts.AddPattern(
1077        URLPattern(URLPattern::SCHEME_HTTPS, "https://www.bar.com/path"));
1078    EXPECT_EQ(expected,
1079              permission_message_util::GetDistinctHosts(
1080                  explicit_hosts, true, true));
1081  }
1082
1083  {
1084    SCOPED_TRACE("paths differ");
1085
1086    // Add some dupes by path.
1087    explicit_hosts.AddPattern(
1088        URLPattern(URLPattern::SCHEME_HTTP, "http://www.bar.com/pathypath"));
1089    EXPECT_EQ(expected,
1090              permission_message_util::GetDistinctHosts(
1091                  explicit_hosts, true, true));
1092  }
1093
1094  {
1095    SCOPED_TRACE("subdomains differ");
1096
1097    // We don't do anything special for subdomains.
1098    explicit_hosts.AddPattern(
1099        URLPattern(URLPattern::SCHEME_HTTP, "http://monkey.www.bar.com/path"));
1100    explicit_hosts.AddPattern(
1101        URLPattern(URLPattern::SCHEME_HTTP, "http://bar.com/path"));
1102
1103    expected.insert("monkey.www.bar.com");
1104    expected.insert("bar.com");
1105
1106    EXPECT_EQ(expected,
1107              permission_message_util::GetDistinctHosts(
1108                  explicit_hosts, true, true));
1109  }
1110
1111  {
1112    SCOPED_TRACE("RCDs differ");
1113
1114    // Now test for RCD uniquing.
1115    explicit_hosts.AddPattern(
1116        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com/path"));
1117    explicit_hosts.AddPattern(
1118        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path"));
1119    explicit_hosts.AddPattern(
1120        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.de/path"));
1121    explicit_hosts.AddPattern(
1122        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca.us/path"));
1123    explicit_hosts.AddPattern(
1124        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.net/path"));
1125    explicit_hosts.AddPattern(
1126        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com.my/path"));
1127
1128    // This is an unknown RCD, which shouldn't be uniqued out.
1129    explicit_hosts.AddPattern(
1130        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.xyzzy/path"));
1131    // But it should only occur once.
1132    explicit_hosts.AddPattern(
1133        URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.xyzzy/path"));
1134
1135    expected.insert("www.foo.xyzzy");
1136
1137    EXPECT_EQ(expected,
1138              permission_message_util::GetDistinctHosts(
1139                  explicit_hosts, true, true));
1140  }
1141
1142  {
1143    SCOPED_TRACE("wildcards");
1144
1145    explicit_hosts.AddPattern(
1146        URLPattern(URLPattern::SCHEME_HTTP, "http://*.google.com/*"));
1147
1148    expected.insert("*.google.com");
1149
1150    EXPECT_EQ(expected,
1151              permission_message_util::GetDistinctHosts(
1152                  explicit_hosts, true, true));
1153  }
1154
1155  {
1156    SCOPED_TRACE("scriptable hosts");
1157
1158    APIPermissionSet empty_perms;
1159    explicit_hosts.ClearPatterns();
1160    URLPatternSet scriptable_hosts;
1161    expected.clear();
1162
1163    explicit_hosts.AddPattern(
1164        URLPattern(URLPattern::SCHEME_HTTP, "http://*.google.com/*"));
1165    scriptable_hosts.AddPattern(
1166        URLPattern(URLPattern::SCHEME_HTTP, "http://*.example.com/*"));
1167
1168    expected.insert("*.google.com");
1169    expected.insert("*.example.com");
1170
1171    scoped_refptr<PermissionSet> perm_set(new PermissionSet(
1172        empty_perms, ManifestPermissionSet(),
1173        explicit_hosts, scriptable_hosts));
1174    EXPECT_EQ(expected,
1175              permission_message_util::GetDistinctHosts(
1176                  perm_set->effective_hosts(), true, true));
1177  }
1178
1179  {
1180    // We don't display warnings for file URLs because they are off by default.
1181    SCOPED_TRACE("file urls");
1182
1183    explicit_hosts.ClearPatterns();
1184    expected.clear();
1185
1186    explicit_hosts.AddPattern(
1187        URLPattern(URLPattern::SCHEME_FILE, "file:///*"));
1188
1189    EXPECT_EQ(expected,
1190              permission_message_util::GetDistinctHosts(
1191                  explicit_hosts, true, true));
1192  }
1193}
1194
1195TEST(PermissionsTest, GetDistinctHosts_ComIsBestRcd) {
1196  URLPatternSet explicit_hosts;
1197  explicit_hosts.AddPattern(
1198      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca/path"));
1199  explicit_hosts.AddPattern(
1200      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.org/path"));
1201  explicit_hosts.AddPattern(
1202      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path"));
1203  explicit_hosts.AddPattern(
1204      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.net/path"));
1205  explicit_hosts.AddPattern(
1206      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.jp/path"));
1207  explicit_hosts.AddPattern(
1208      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.com/path"));
1209
1210  std::set<std::string> expected;
1211  expected.insert("www.foo.com");
1212  EXPECT_EQ(expected,
1213            permission_message_util::GetDistinctHosts(
1214                explicit_hosts, true, true));
1215}
1216
1217TEST(PermissionsTest, GetDistinctHosts_NetIs2ndBestRcd) {
1218  URLPatternSet explicit_hosts;
1219  explicit_hosts.AddPattern(
1220      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca/path"));
1221  explicit_hosts.AddPattern(
1222      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.org/path"));
1223  explicit_hosts.AddPattern(
1224      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path"));
1225  explicit_hosts.AddPattern(
1226      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.net/path"));
1227  explicit_hosts.AddPattern(
1228      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.jp/path"));
1229  // No http://www.foo.com/path
1230
1231  std::set<std::string> expected;
1232  expected.insert("www.foo.net");
1233  EXPECT_EQ(expected,
1234            permission_message_util::GetDistinctHosts(
1235                explicit_hosts, true, true));
1236}
1237
1238TEST(PermissionsTest, GetDistinctHosts_OrgIs3rdBestRcd) {
1239  URLPatternSet explicit_hosts;
1240  explicit_hosts.AddPattern(
1241      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca/path"));
1242  explicit_hosts.AddPattern(
1243      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.org/path"));
1244  explicit_hosts.AddPattern(
1245      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path"));
1246  // No http://www.foo.net/path
1247  explicit_hosts.AddPattern(
1248      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.jp/path"));
1249  // No http://www.foo.com/path
1250
1251  std::set<std::string> expected;
1252  expected.insert("www.foo.org");
1253  EXPECT_EQ(expected,
1254            permission_message_util::GetDistinctHosts(
1255                explicit_hosts, true, true));
1256}
1257
1258TEST(PermissionsTest, GetDistinctHosts_FirstInListIs4thBestRcd) {
1259  URLPatternSet explicit_hosts;
1260  explicit_hosts.AddPattern(
1261      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.ca/path"));
1262  // No http://www.foo.org/path
1263  explicit_hosts.AddPattern(
1264      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.co.uk/path"));
1265  // No http://www.foo.net/path
1266  explicit_hosts.AddPattern(
1267      URLPattern(URLPattern::SCHEME_HTTP, "http://www.foo.jp/path"));
1268  // No http://www.foo.com/path
1269
1270  std::set<std::string> expected;
1271  expected.insert("www.foo.ca");
1272  EXPECT_EQ(expected,
1273            permission_message_util::GetDistinctHosts(
1274                explicit_hosts, true, true));
1275}
1276
1277TEST(PermissionsTest, IsHostPrivilegeIncrease) {
1278  Manifest::Type type = Manifest::TYPE_EXTENSION;
1279  const PermissionMessageProvider* provider = PermissionMessageProvider::Get();
1280  ManifestPermissionSet empty_manifest_permissions;
1281  URLPatternSet elist1;
1282  URLPatternSet elist2;
1283  URLPatternSet slist1;
1284  URLPatternSet slist2;
1285  scoped_refptr<PermissionSet> set1;
1286  scoped_refptr<PermissionSet> set2;
1287  APIPermissionSet empty_perms;
1288  elist1.AddPattern(
1289      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com.hk/path"));
1290  elist1.AddPattern(
1291      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/path"));
1292
1293  // Test that the host order does not matter.
1294  elist2.AddPattern(
1295      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/path"));
1296  elist2.AddPattern(
1297      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com.hk/path"));
1298
1299  set1 = new PermissionSet(empty_perms, empty_manifest_permissions,
1300                           elist1, slist1);
1301  set2 = new PermissionSet(empty_perms, empty_manifest_permissions,
1302                           elist2, slist2);
1303
1304  EXPECT_FALSE(provider->IsPrivilegeIncrease(set1, set2, type));
1305  EXPECT_FALSE(provider->IsPrivilegeIncrease(set2, set1, type));
1306
1307  // Test that paths are ignored.
1308  elist2.ClearPatterns();
1309  elist2.AddPattern(
1310      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/*"));
1311  set2 = new PermissionSet(empty_perms, empty_manifest_permissions,
1312                           elist2, slist2);
1313  EXPECT_FALSE(provider->IsPrivilegeIncrease(set1, set2, type));
1314  EXPECT_FALSE(provider->IsPrivilegeIncrease(set2, set1, type));
1315
1316  // Test that RCDs are ignored.
1317  elist2.ClearPatterns();
1318  elist2.AddPattern(
1319      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com.hk/*"));
1320  set2 = new PermissionSet(empty_perms, empty_manifest_permissions,
1321                           elist2, slist2);
1322  EXPECT_FALSE(provider->IsPrivilegeIncrease(set1, set2, type));
1323  EXPECT_FALSE(provider->IsPrivilegeIncrease(set2, set1, type));
1324
1325  // Test that subdomain wildcards are handled properly.
1326  elist2.ClearPatterns();
1327  elist2.AddPattern(
1328      URLPattern(URLPattern::SCHEME_HTTP, "http://*.google.com.hk/*"));
1329  set2 = new PermissionSet(empty_perms, empty_manifest_permissions,
1330                           elist2, slist2);
1331  EXPECT_TRUE(provider->IsPrivilegeIncrease(set1, set2, type));
1332  // TODO(jstritar): Does not match subdomains properly. http://crbug.com/65337
1333  // EXPECT_FALSE(provider->IsPrivilegeIncrease(set2, set1, type));
1334
1335  // Test that different domains count as different hosts.
1336  elist2.ClearPatterns();
1337  elist2.AddPattern(
1338      URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/path"));
1339  elist2.AddPattern(
1340      URLPattern(URLPattern::SCHEME_HTTP, "http://www.example.org/path"));
1341  set2 = new PermissionSet(empty_perms, empty_manifest_permissions,
1342                           elist2, slist2);
1343  EXPECT_TRUE(provider->IsPrivilegeIncrease(set1, set2, type));
1344  EXPECT_FALSE(provider->IsPrivilegeIncrease(set2, set1, type));
1345
1346  // Test that different subdomains count as different hosts.
1347  elist2.ClearPatterns();
1348  elist2.AddPattern(
1349      URLPattern(URLPattern::SCHEME_HTTP, "http://mail.google.com/*"));
1350  set2 = new PermissionSet(empty_perms, empty_manifest_permissions,
1351                           elist2, slist2);
1352  EXPECT_TRUE(provider->IsPrivilegeIncrease(set1, set2, type));
1353  EXPECT_TRUE(provider->IsPrivilegeIncrease(set2, set1, type));
1354
1355  // Test that platform apps do not have host permissions increases.
1356  type = Manifest::TYPE_PLATFORM_APP;
1357  EXPECT_FALSE(provider->IsPrivilegeIncrease(set1, set2, type));
1358  EXPECT_FALSE(provider->IsPrivilegeIncrease(set2, set1, type));
1359}
1360
1361TEST(PermissionsTest, GetAPIsAsStrings) {
1362  APIPermissionSet apis;
1363  URLPatternSet empty_set;
1364
1365  apis.insert(APIPermission::kProxy);
1366  apis.insert(APIPermission::kBackground);
1367  apis.insert(APIPermission::kNotification);
1368  apis.insert(APIPermission::kTab);
1369
1370  scoped_refptr<PermissionSet> perm_set = new PermissionSet(
1371      apis, ManifestPermissionSet(), empty_set, empty_set);
1372  std::set<std::string> api_names = perm_set->GetAPIsAsStrings();
1373
1374  // The result is correct if it has the same number of elements
1375  // and we can convert it back to the id set.
1376  EXPECT_EQ(4u, api_names.size());
1377  EXPECT_EQ(apis,
1378            PermissionsInfo::GetInstance()->GetAllByName(api_names));
1379}
1380
1381TEST(PermissionsTest, IsEmpty) {
1382  APIPermissionSet empty_apis;
1383  URLPatternSet empty_extent;
1384
1385  scoped_refptr<PermissionSet> empty = new PermissionSet();
1386  EXPECT_TRUE(empty->IsEmpty());
1387  scoped_refptr<PermissionSet> perm_set;
1388
1389  perm_set = new PermissionSet(empty_apis, ManifestPermissionSet(),
1390                               empty_extent, empty_extent);
1391  EXPECT_TRUE(perm_set->IsEmpty());
1392
1393  APIPermissionSet non_empty_apis;
1394  non_empty_apis.insert(APIPermission::kBackground);
1395  perm_set = new PermissionSet(non_empty_apis, ManifestPermissionSet(),
1396                               empty_extent, empty_extent);
1397  EXPECT_FALSE(perm_set->IsEmpty());
1398
1399  // Try non standard host
1400  URLPatternSet non_empty_extent;
1401  AddPattern(&non_empty_extent, "http://www.google.com/*");
1402
1403  perm_set = new PermissionSet(empty_apis, ManifestPermissionSet(),
1404                               non_empty_extent, empty_extent);
1405  EXPECT_FALSE(perm_set->IsEmpty());
1406
1407  perm_set = new PermissionSet(empty_apis, ManifestPermissionSet(),
1408                               empty_extent, non_empty_extent);
1409  EXPECT_FALSE(perm_set->IsEmpty());
1410}
1411
1412TEST(PermissionsTest, ImpliedPermissions) {
1413  URLPatternSet empty_extent;
1414  APIPermissionSet apis;
1415  apis.insert(APIPermission::kWebRequest);
1416  apis.insert(APIPermission::kFileBrowserHandler);
1417  EXPECT_EQ(2U, apis.size());
1418
1419  scoped_refptr<PermissionSet> perm_set;
1420  perm_set = new PermissionSet(apis, ManifestPermissionSet(),
1421                               empty_extent, empty_extent);
1422  EXPECT_EQ(4U, perm_set->apis().size());
1423}
1424
1425TEST(PermissionsTest, SyncFileSystemPermission) {
1426  scoped_refptr<Extension> extension = LoadManifest(
1427      "permissions", "sync_file_system.json");
1428  APIPermissionSet apis;
1429  apis.insert(APIPermission::kSyncFileSystem);
1430  EXPECT_TRUE(extension->is_platform_app());
1431  EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kSyncFileSystem));
1432  std::vector<base::string16> warnings =
1433      PermissionsData::GetPermissionMessageStrings(extension.get());
1434  EXPECT_TRUE(Contains(warnings, "Store data in your Google Drive account"));
1435  ASSERT_EQ(1u, warnings.size());
1436}
1437
1438// Make sure that we don't crash when we're trying to show the permissions
1439// even though chrome://thumb (and everything that's not chrome://favicon with
1440// a chrome:// scheme) is not a valid permission.
1441// More details here: crbug/246314.
1442TEST(PermissionsTest, ChromeURLs) {
1443  URLPatternSet allowed_hosts;
1444  allowed_hosts.AddPattern(
1445      URLPattern(URLPattern::SCHEME_ALL, "http://www.google.com/"));
1446  allowed_hosts.AddPattern(
1447      URLPattern(URLPattern::SCHEME_ALL, "chrome://favicon/"));
1448  allowed_hosts.AddPattern(
1449      URLPattern(URLPattern::SCHEME_ALL, "chrome://thumb/"));
1450  scoped_refptr<PermissionSet> permissions(
1451      new PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
1452                        allowed_hosts, URLPatternSet()));
1453  PermissionMessageProvider::Get()->
1454      GetPermissionMessages(permissions, Manifest::TYPE_EXTENSION);
1455}
1456
1457TEST(PermissionsTest, IsPrivilegeIncrease_DeclarativeWebRequest) {
1458  scoped_refptr<Extension> extension(
1459      LoadManifest("permissions", "permissions_all_urls.json"));
1460  scoped_refptr<const PermissionSet> permissions(
1461      extension->GetActivePermissions());
1462
1463  scoped_refptr<Extension> extension_dwr(
1464      LoadManifest("permissions", "web_request_all_host_permissions.json"));
1465  scoped_refptr<const PermissionSet> permissions_dwr(
1466      extension_dwr->GetActivePermissions());
1467
1468  EXPECT_FALSE(PermissionMessageProvider::Get()->
1469                   IsPrivilegeIncrease(permissions.get(),
1470                                       permissions_dwr.get(),
1471                                       extension->GetType()));
1472}
1473
1474}  // namespace extensions
1475