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/memory/scoped_ptr.h" 6 #include "base/values.h" 7 #include "chrome/browser/extensions/api/permissions/permissions_api_helpers.h" 8 #include "chrome/common/extensions/api/permissions.h" 9 #include "extensions/common/permissions/permission_set.h" 10 #include "extensions/common/url_pattern_set.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 #include "url/gurl.h" 13 14 using extensions::api::permissions::Permissions; 15 using extensions::permissions_api_helpers::PackPermissionSet; 16 using extensions::permissions_api_helpers::UnpackPermissionSet; 17 18 namespace extensions { 19 20 namespace { 21 22 static void AddPattern(URLPatternSet* extent, const std::string& pattern) { 23 int schemes = URLPattern::SCHEME_ALL; 24 extent->AddPattern(URLPattern(schemes, pattern)); 25 } 26 27 } // namespace 28 29 // Tests that we can convert PermissionSets to and from values. 30 TEST(ExtensionPermissionsAPIHelpers, Pack) { 31 APIPermissionSet apis; 32 apis.insert(APIPermission::kTab); 33 apis.insert(APIPermission::kFileBrowserHandler); 34 // Note: kFileBrowserHandler implies kFileBrowserHandlerInternal. 35 URLPatternSet hosts; 36 AddPattern(&hosts, "http://a.com/*"); 37 AddPattern(&hosts, "http://b.com/*"); 38 39 scoped_refptr<PermissionSet> permission_set = 40 new PermissionSet(apis, ManifestPermissionSet(), hosts, URLPatternSet()); 41 42 // Pack the permission set to value and verify its contents. 43 scoped_ptr<Permissions> permissions(PackPermissionSet(permission_set.get())); 44 scoped_ptr<base::DictionaryValue> value(permissions->ToValue()); 45 base::ListValue* api_list = NULL; 46 base::ListValue* origin_list = NULL; 47 EXPECT_TRUE(value->GetList("permissions", &api_list)); 48 EXPECT_TRUE(value->GetList("origins", &origin_list)); 49 50 EXPECT_EQ(3u, api_list->GetSize()); 51 EXPECT_EQ(2u, origin_list->GetSize()); 52 53 std::string expected_apis[] = {"tabs", "fileBrowserHandler", 54 "fileBrowserHandlerInternal"}; 55 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(expected_apis); ++i) { 56 scoped_ptr<base::Value> value(new base::StringValue(expected_apis[i])); 57 EXPECT_NE(api_list->end(), api_list->Find(*value)); 58 } 59 60 std::string expected_origins[] = { "http://a.com/*", "http://b.com/*" }; 61 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(expected_origins); ++i) { 62 scoped_ptr<base::Value> value(new base::StringValue(expected_origins[i])); 63 EXPECT_NE(origin_list->end(), origin_list->Find(*value)); 64 } 65 66 // Unpack the value back to a permission set and make sure its equal to the 67 // original one. 68 scoped_refptr<PermissionSet> from_value; 69 std::string error; 70 Permissions permissions_object; 71 EXPECT_TRUE(Permissions::Populate(*value, &permissions_object)); 72 from_value = UnpackPermissionSet(permissions_object, true, &error); 73 EXPECT_TRUE(error.empty()); 74 75 EXPECT_EQ(*permission_set.get(), *from_value.get()); 76 } 77 78 // Tests various error conditions and edge cases when unpacking values 79 // into PermissionSets. 80 TEST(ExtensionPermissionsAPIHelpers, Unpack) { 81 scoped_ptr<base::ListValue> apis(new base::ListValue()); 82 apis->Append(new base::StringValue("tabs")); 83 scoped_ptr<base::ListValue> origins(new base::ListValue()); 84 origins->Append(new base::StringValue("http://a.com/*")); 85 86 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); 87 scoped_refptr<PermissionSet> permissions; 88 std::string error; 89 90 // Origins shouldn't have to be present. 91 { 92 Permissions permissions_object; 93 value->Set("permissions", apis->DeepCopy()); 94 EXPECT_TRUE(Permissions::Populate(*value, &permissions_object)); 95 permissions = UnpackPermissionSet(permissions_object, true, &error); 96 EXPECT_TRUE(permissions->HasAPIPermission(APIPermission::kTab)); 97 EXPECT_TRUE(permissions.get()); 98 EXPECT_TRUE(error.empty()); 99 } 100 101 // The api permissions don't need to be present either. 102 { 103 Permissions permissions_object; 104 value->Clear(); 105 value->Set("origins", origins->DeepCopy()); 106 EXPECT_TRUE(Permissions::Populate(*value, &permissions_object)); 107 permissions = UnpackPermissionSet(permissions_object, true, &error); 108 EXPECT_TRUE(permissions.get()); 109 EXPECT_TRUE(error.empty()); 110 EXPECT_TRUE(permissions->HasExplicitAccessToOrigin(GURL("http://a.com/"))); 111 } 112 113 // Throw errors for non-string API permissions. 114 { 115 Permissions permissions_object; 116 value->Clear(); 117 scoped_ptr<base::ListValue> invalid_apis(apis->DeepCopy()); 118 invalid_apis->Append(new base::FundamentalValue(3)); 119 value->Set("permissions", invalid_apis->DeepCopy()); 120 EXPECT_FALSE(Permissions::Populate(*value, &permissions_object)); 121 } 122 123 // Throw errors for non-string origins. 124 { 125 Permissions permissions_object; 126 value->Clear(); 127 scoped_ptr<base::ListValue> invalid_origins(origins->DeepCopy()); 128 invalid_origins->Append(new base::FundamentalValue(3)); 129 value->Set("origins", invalid_origins->DeepCopy()); 130 EXPECT_FALSE(Permissions::Populate(*value, &permissions_object)); 131 } 132 133 // Throw errors when "origins" or "permissions" are not list values. 134 { 135 Permissions permissions_object; 136 value->Clear(); 137 value->Set("origins", new base::FundamentalValue(2)); 138 EXPECT_FALSE(Permissions::Populate(*value, &permissions_object)); 139 } 140 141 { 142 Permissions permissions_object; 143 value->Clear(); 144 value->Set("permissions", new base::FundamentalValue(2)); 145 EXPECT_FALSE(Permissions::Populate(*value, &permissions_object)); 146 } 147 148 // Additional fields should be allowed. 149 { 150 Permissions permissions_object; 151 value->Clear(); 152 value->Set("origins", origins->DeepCopy()); 153 value->Set("random", new base::FundamentalValue(3)); 154 EXPECT_TRUE(Permissions::Populate(*value, &permissions_object)); 155 permissions = UnpackPermissionSet(permissions_object, true, &error); 156 EXPECT_TRUE(permissions.get()); 157 EXPECT_TRUE(error.empty()); 158 EXPECT_TRUE(permissions->HasExplicitAccessToOrigin(GURL("http://a.com/"))); 159 } 160 161 // Unknown permissions should throw an error. 162 { 163 Permissions permissions_object; 164 value->Clear(); 165 scoped_ptr<base::ListValue> invalid_apis(apis->DeepCopy()); 166 invalid_apis->Append(new base::StringValue("unknown_permission")); 167 value->Set("permissions", invalid_apis->DeepCopy()); 168 EXPECT_TRUE(Permissions::Populate(*value, &permissions_object)); 169 permissions = UnpackPermissionSet(permissions_object, true, &error); 170 EXPECT_FALSE(permissions.get()); 171 EXPECT_FALSE(error.empty()); 172 EXPECT_EQ(error, "'unknown_permission' is not a recognized permission."); 173 } 174 } 175 176 } // namespace extensions 177