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