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