blob: 6c961c8683cdb6af817d6b19471b3ce5daa27dee [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// 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/logging.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.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/test_browser_thread_bundle.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/permissions/api_permission.h"
#include "testing/gtest/include/gtest/gtest.h"
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(APIPermission::ID 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(
Manifest::Location location,
const base::ListValue* required_permissions,
const base::ListValue* optional_permissions) {
base::DictionaryValue manifest_dict;
manifest_dict.SetString(manifest_keys::kName, "test");
manifest_dict.SetString(manifest_keys::kVersion, "0.1");
manifest_dict.SetInteger(manifest_keys::kManifestVersion, 2);
if (required_permissions) {
manifest_dict.Set(manifest_keys::kPermissions,
required_permissions->CreateDeepCopy());
}
if (optional_permissions) {
manifest_dict.Set(manifest_keys::kOptionalPermissions,
optional_permissions->CreateDeepCopy());
}
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::TestBrowserThreadBundle test_browser_thread_bundle_;
std::unique_ptr<TestingProfile> profile_;
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::ListValue required_permissions;
required_permissions.AppendString(
GetAPIPermissionName(APIPermission::kDownloads));
required_permissions.AppendString(
GetAPIPermissionName(APIPermission::kCookie));
base::ListValue optional_permissions;
optional_permissions.AppendString(
GetAPIPermissionName(APIPermission::kProxy));
scoped_refptr<const Extension> extension =
CreateExtensionWithPermission(Manifest::EXTERNAL_POLICY_DOWNLOAD,
&required_permissions,
&optional_permissions);
base::string16 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_);
pref.AddBlockedPermission("*",
GetAPIPermissionName(APIPermission::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_);
pref.AddBlockedPermission("*",
GetAPIPermissionName(APIPermission::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_);
pref.AddAllowedPermission(extension->id(),
GetAPIPermissionName(APIPermission::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_);
pref.AddBlockedPermission(extension->id(),
GetAPIPermissionName(APIPermission::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_);
pref.UnsetBlockedPermissions(extension->id());
pref.UnsetAllowedPermissions(extension->id());
pref.ClearBlockedPermissions("*");
pref.AddBlockedPermission("*",
GetAPIPermissionName(APIPermission::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_);
pref.UnsetPerExtensionSettings(extension->id());
pref.UnsetPerExtensionSettings(extension->id());
pref.ClearBlockedPermissions("*");
pref.AddBlockedPermission("*",
GetAPIPermissionName(APIPermission::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_);
pref.UnsetPerExtensionSettings(extension->id());
pref.UnsetPerExtensionSettings(extension->id());
pref.SetBlockedInstallMessage(extension->id(), blocked_install_message);
pref.ClearBlockedPermissions("*");
pref.AddBlockedPermission(extension->id(),
GetAPIPermissionName(APIPermission::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