1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/permissions_based_management_policy_provider.h"
#include <memory>
#include <string>
#include <vector>
#include "base/check.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_management.h"
#include "chrome/browser/extensions/extension_management_test_util.h"
#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
#include "chrome/test/base/testing_profile.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/mojom/api_permission_id.mojom-shared.h"
#include "extensions/common/permissions/api_permission.h"
#include "testing/gtest/include/gtest/gtest.h"
using extensions::mojom::APIPermissionID;
namespace extensions {
class PermissionsBasedManagementPolicyProviderTest : public testing::Test {
public:
typedef ExtensionManagementPrefUpdater<
sync_preferences::TestingPrefServiceSyncable>
PrefUpdater;
PermissionsBasedManagementPolicyProviderTest()
: profile_(std::make_unique<TestingProfile>()),
pref_service_(profile_->GetTestingPrefService()),
settings_(std::make_unique<ExtensionManagement>(profile_.get())),
provider_(settings_.get()) {}
void SetUp() override {}
void TearDown() override {}
// Get API permissions name for |id|, we cannot use arbitrary strings since
// they will be ignored by ExtensionManagementService.
std::string GetAPIPermissionName(APIPermissionID id) {
for (const auto& perm : chrome_api_permissions::GetPermissionInfos()) {
if (perm.id == id) {
return perm.name;
}
}
ADD_FAILURE() << "Permission not found: " << id;
return std::string();
}
// Create an extension with specified |location|, |required_permissions| and
// |optional_permissions|.
scoped_refptr<const Extension> CreateExtensionWithPermission(
mojom::ManifestLocation location,
const base::Value::List* required_permissions,
const base::Value::List* optional_permissions) {
base::Value::Dict manifest_dict;
manifest_dict.Set(manifest_keys::kName, "test");
manifest_dict.Set(manifest_keys::kVersion, "0.1");
manifest_dict.Set(manifest_keys::kManifestVersion, 2);
if (required_permissions) {
manifest_dict.Set(manifest_keys::kPermissions,
required_permissions->Clone());
}
if (optional_permissions) {
manifest_dict.Set(manifest_keys::kOptionalPermissions,
optional_permissions->Clone());
}
std::string error;
scoped_refptr<const Extension> extension = Extension::Create(
base::FilePath(), location, manifest_dict, Extension::NO_FLAGS, &error);
CHECK(extension.get()) << error;
return extension;
}
protected:
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<TestingProfile> profile_;
raw_ptr<sync_preferences::TestingPrefServiceSyncable> pref_service_;
std::unique_ptr<ExtensionManagement> settings_;
PermissionsBasedManagementPolicyProvider provider_;
};
// Verifies that extensions with conflicting permissions cannot be loaded.
TEST_F(PermissionsBasedManagementPolicyProviderTest, APIPermissions) {
// Prepares the extension manifest.
base::Value::List required_permissions;
required_permissions.Append(
GetAPIPermissionName(APIPermissionID::kDownloads));
required_permissions.Append(GetAPIPermissionName(APIPermissionID::kCookie));
base::Value::List optional_permissions;
optional_permissions.Append(GetAPIPermissionName(APIPermissionID::kProxy));
scoped_refptr<const Extension> extension = CreateExtensionWithPermission(
mojom::ManifestLocation::kExternalPolicyDownload, &required_permissions,
&optional_permissions);
std::u16string error16;
// The extension should be allowed to be loaded by default.
error16.clear();
EXPECT_TRUE(provider_.UserMayLoad(extension.get(), &error16));
EXPECT_TRUE(error16.empty());
// Blocks kProxy by default. The test extension should still be allowed.
{
PrefUpdater pref(pref_service_.get());
pref.AddBlockedPermission("*",
GetAPIPermissionName(APIPermissionID::kProxy));
}
error16.clear();
EXPECT_TRUE(provider_.UserMayLoad(extension.get(), &error16));
EXPECT_TRUE(error16.empty());
// Blocks kCookie this time. The test extension should not be allowed now.
{
PrefUpdater pref(pref_service_.get());
pref.AddBlockedPermission("*",
GetAPIPermissionName(APIPermissionID::kCookie));
}
error16.clear();
EXPECT_FALSE(provider_.UserMayLoad(extension.get(), &error16));
EXPECT_FALSE(error16.empty());
// Explictly allows kCookie for test extension. It should be allowed again.
{
PrefUpdater pref(pref_service_.get());
pref.AddAllowedPermission(extension->id(),
GetAPIPermissionName(APIPermissionID::kCookie));
}
error16.clear();
EXPECT_TRUE(provider_.UserMayLoad(extension.get(), &error16));
EXPECT_TRUE(error16.empty());
// Explictly blocks kCookie for test extension. It should still be allowed.
{
PrefUpdater pref(pref_service_.get());
pref.AddBlockedPermission(extension->id(),
GetAPIPermissionName(APIPermissionID::kCookie));
}
error16.clear();
EXPECT_TRUE(provider_.UserMayLoad(extension.get(), &error16));
EXPECT_TRUE(error16.empty());
// Any extension specific definition overrides all defaults, even if blank.
{
PrefUpdater pref(pref_service_.get());
pref.UnsetBlockedPermissions(extension->id());
pref.UnsetAllowedPermissions(extension->id());
pref.ClearBlockedPermissions("*");
pref.AddBlockedPermission(
"*", GetAPIPermissionName(APIPermissionID::kDownloads));
}
error16.clear();
EXPECT_TRUE(provider_.UserMayLoad(extension.get(), &error16));
EXPECT_TRUE(error16.empty());
// Blocks kDownloads by default. It should be blocked.
{
PrefUpdater pref(pref_service_.get());
pref.UnsetPerExtensionSettings(extension->id());
pref.UnsetPerExtensionSettings(extension->id());
pref.ClearBlockedPermissions("*");
pref.AddBlockedPermission(
"*", GetAPIPermissionName(APIPermissionID::kDownloads));
}
error16.clear();
EXPECT_FALSE(provider_.UserMayLoad(extension.get(), &error16));
EXPECT_FALSE(error16.empty());
EXPECT_EQ("test (extension ID \"" + extension->id() +
"\") is blocked by the administrator. ",
base::UTF16ToASCII(error16));
// Set custom error message to display to user when install blocked.
const std::string blocked_install_message =
"Visit https://example.com/exception";
{
PrefUpdater pref(pref_service_.get());
pref.UnsetPerExtensionSettings(extension->id());
pref.UnsetPerExtensionSettings(extension->id());
pref.SetBlockedInstallMessage(extension->id(), blocked_install_message);
pref.ClearBlockedPermissions("*");
pref.AddBlockedPermission(
extension->id(), GetAPIPermissionName(APIPermissionID::kDownloads));
}
error16.clear();
EXPECT_FALSE(provider_.UserMayLoad(extension.get(), &error16));
EXPECT_FALSE(error16.empty());
EXPECT_EQ("test (extension ID \"" + extension->id() +
"\") is blocked by the administrator. " +
blocked_install_message,
base::UTF16ToASCII(error16));
}
} // namespace extensions
|