Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / common / extensions / permissions / permission_set_unittest.cc
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
30 using extension_test_util::LoadManifest;
31
32 namespace extensions {
33
34 namespace {
35
36 static void AddPattern(URLPatternSet* extent, const std::string& pattern) {
37   int schemes = URLPattern::SCHEME_ALL;
38   extent->AddPattern(URLPattern(schemes, pattern));
39 }
40
41 size_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
51 bool 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.
59 TEST(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.
69 TEST(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
77 TEST(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
91 TEST(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.
112 TEST(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
130 TEST(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
210 TEST(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
234 TEST(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
356 TEST(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
468 TEST(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
567 TEST(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
632 TEST(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
792 TEST(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.
815 TEST(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
844 TEST(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
859 TEST(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
969 TEST(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
1093 TEST(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
1136 TEST(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
1149 TEST(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
1169 TEST(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
1202 TEST(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
1242 TEST(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
1276 TEST(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
1289 TEST(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
1304 TEST(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
1331 TEST(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
1356 TEST(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
1371 bool 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
1395 TEST(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
1420 TEST(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
1578 TEST(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
1600 TEST(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
1621 TEST(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
1641 TEST(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
1660 TEST(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
1744 TEST(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
1764 TEST(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
1795 TEST(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
1807 TEST(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.
1825 TEST(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
1840 TEST(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