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