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