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 "chrome/common/extensions/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::kWebRequest); 34 // Note: kWebRequest implies also kWebRequestInternal. 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, 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", "webRequest" }; 54 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(expected_apis); ++i) { 55 scoped_ptr<Value> value(Value::CreateStringValue(expected_apis[i])); 56 EXPECT_NE(api_list->end(), api_list->Find(*value)); 57 } 58 59 std::string expected_origins[] = { "http://a.com/*", "http://b.com/*" }; 60 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(expected_origins); ++i) { 61 scoped_ptr<Value> value(Value::CreateStringValue(expected_origins[i])); 62 EXPECT_NE(origin_list->end(), origin_list->Find(*value)); 63 } 64 65 // Unpack the value back to a permission set and make sure its equal to the 66 // original one. 67 scoped_refptr<PermissionSet> from_value; 68 std::string error; 69 Permissions permissions_object; 70 EXPECT_TRUE(Permissions::Populate(*value, &permissions_object)); 71 from_value = UnpackPermissionSet(permissions_object, true, &error); 72 EXPECT_TRUE(error.empty()); 73 74 EXPECT_EQ(*permission_set.get(), *from_value.get()); 75 } 76 77 // Tests various error conditions and edge cases when unpacking values 78 // into PermissionSets. 79 TEST(ExtensionPermissionsAPIHelpers, Unpack) { 80 scoped_ptr<base::ListValue> apis(new base::ListValue()); 81 apis->Append(Value::CreateStringValue("tabs")); 82 scoped_ptr<base::ListValue> origins(new base::ListValue()); 83 origins->Append(Value::CreateStringValue("http://a.com/*")); 84 85 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); 86 scoped_refptr<PermissionSet> permissions; 87 std::string error; 88 89 // Origins shouldn't have to be present. 90 { 91 Permissions permissions_object; 92 value->Set("permissions", apis->DeepCopy()); 93 EXPECT_TRUE(Permissions::Populate(*value, &permissions_object)); 94 permissions = UnpackPermissionSet(permissions_object, true, &error); 95 EXPECT_TRUE(permissions->HasAPIPermission(APIPermission::kTab)); 96 EXPECT_TRUE(permissions.get()); 97 EXPECT_TRUE(error.empty()); 98 } 99 100 // The api permissions don't need to be present either. 101 { 102 Permissions permissions_object; 103 value->Clear(); 104 value->Set("origins", origins->DeepCopy()); 105 EXPECT_TRUE(Permissions::Populate(*value, &permissions_object)); 106 permissions = UnpackPermissionSet(permissions_object, true, &error); 107 EXPECT_TRUE(permissions.get()); 108 EXPECT_TRUE(error.empty()); 109 EXPECT_TRUE(permissions->HasExplicitAccessToOrigin(GURL("http://a.com/"))); 110 } 111 112 // Throw errors for non-string API permissions. 113 { 114 Permissions permissions_object; 115 value->Clear(); 116 scoped_ptr<base::ListValue> invalid_apis(apis->DeepCopy()); 117 invalid_apis->Append(Value::CreateIntegerValue(3)); 118 value->Set("permissions", invalid_apis->DeepCopy()); 119 EXPECT_FALSE(Permissions::Populate(*value, &permissions_object)); 120 } 121 122 // Throw errors for non-string origins. 123 { 124 Permissions permissions_object; 125 value->Clear(); 126 scoped_ptr<base::ListValue> invalid_origins(origins->DeepCopy()); 127 invalid_origins->Append(Value::CreateIntegerValue(3)); 128 value->Set("origins", invalid_origins->DeepCopy()); 129 EXPECT_FALSE(Permissions::Populate(*value, &permissions_object)); 130 } 131 132 // Throw errors when "origins" or "permissions" are not list values. 133 { 134 Permissions permissions_object; 135 value->Clear(); 136 value->Set("origins", Value::CreateIntegerValue(2)); 137 EXPECT_FALSE(Permissions::Populate(*value, &permissions_object)); 138 } 139 140 { 141 Permissions permissions_object; 142 value->Clear(); 143 value->Set("permissions", Value::CreateIntegerValue(2)); 144 EXPECT_FALSE(Permissions::Populate(*value, &permissions_object)); 145 } 146 147 // Additional fields should be allowed. 148 { 149 Permissions permissions_object; 150 value->Clear(); 151 value->Set("origins", origins->DeepCopy()); 152 value->Set("random", Value::CreateIntegerValue(3)); 153 EXPECT_TRUE(Permissions::Populate(*value, &permissions_object)); 154 permissions = UnpackPermissionSet(permissions_object, true, &error); 155 EXPECT_TRUE(permissions.get()); 156 EXPECT_TRUE(error.empty()); 157 EXPECT_TRUE(permissions->HasExplicitAccessToOrigin(GURL("http://a.com/"))); 158 } 159 160 // Unknown permissions should throw an error. 161 { 162 Permissions permissions_object; 163 value->Clear(); 164 scoped_ptr<base::ListValue> invalid_apis(apis->DeepCopy()); 165 invalid_apis->Append(Value::CreateStringValue("unknown_permission")); 166 value->Set("permissions", invalid_apis->DeepCopy()); 167 EXPECT_TRUE(Permissions::Populate(*value, &permissions_object)); 168 permissions = UnpackPermissionSet(permissions_object, true, &error); 169 EXPECT_FALSE(permissions.get()); 170 EXPECT_FALSE(error.empty()); 171 EXPECT_EQ(error, "'unknown_permission' is not a recognized permission."); 172 } 173 } 174 175 } // namespace extensions 176