diff options
author | derat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-08 09:39:47 +0000 |
---|---|---|
committer | derat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-08 09:39:47 +0000 |
commit | 1ff3fac6be85e0382e9e0362df12464afb0fc2d3 (patch) | |
tree | 6a0cec570976bed89c557c62a3d0301dd6fdf181 /extensions | |
parent | 665d1d57eff29f1757e16e3891464d6cb5532e22 (diff) | |
download | chromium_src-1ff3fac6be85e0382e9e0362df12464afb0fc2d3.zip chromium_src-1ff3fac6be85e0382e9e0362df12464afb0fc2d3.tar.gz chromium_src-1ff3fac6be85e0382e9e0362df12464afb0fc2d3.tar.bz2 |
Move extensions::admin_policy code to extensions/browser.
Also temporarily permit inclusion of
grit/generated_resources.h from within extensions/browser.
(Longer-term, we'll want to move resources needed by
extensions/ into their own file.)
BUG=313284
Review URL: https://codereview.chromium.org/64643003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@233847 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/browser/DEPS | 1 | ||||
-rw-r--r-- | extensions/browser/admin_policy.cc | 121 | ||||
-rw-r--r-- | extensions/browser/admin_policy.h | 42 | ||||
-rw-r--r-- | extensions/browser/admin_policy_unittest.cc | 196 | ||||
-rw-r--r-- | extensions/extensions.gyp | 3 |
5 files changed, 363 insertions, 0 deletions
diff --git a/extensions/browser/DEPS b/extensions/browser/DEPS index 737b8eb..0f912bf 100644 --- a/extensions/browser/DEPS +++ b/extensions/browser/DEPS @@ -16,6 +16,7 @@ include_rules = [ "+chrome/common/extensions/background_info.h", "+chrome/common/extensions/extension.h", "+chrome/common/extensions/extension_messages.h", + "+grit/generated_resources.h", ] specific_include_rules = { diff --git a/extensions/browser/admin_policy.cc b/extensions/browser/admin_policy.cc new file mode 100644 index 0000000..2cc0b57 --- /dev/null +++ b/extensions/browser/admin_policy.cc @@ -0,0 +1,121 @@ +// Copyright 2013 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 "extensions/browser/admin_policy.h" + +#include "base/strings/utf_string_conversions.h" +#include "chrome/common/extensions/extension.h" +#include "extensions/common/manifest.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +namespace { + +bool ManagementPolicyImpl(const extensions::Extension* extension, + string16* error, + bool modifiable_value) { + bool modifiable = + extension->location() != extensions::Manifest::COMPONENT && + !extensions::Manifest::IsPolicyLocation(extension->location()); + // Some callers equate "no restriction" to true, others to false. + if (modifiable) + return modifiable_value; + + if (error) { + *error = l10n_util::GetStringFUTF16( + IDS_EXTENSION_CANT_MODIFY_POLICY_REQUIRED, + UTF8ToUTF16(extension->name())); + } + return !modifiable_value; +} + +bool ReturnLoadError(const extensions::Extension* extension, string16* error) { + if (error) { + *error = l10n_util::GetStringFUTF16( + IDS_EXTENSION_CANT_INSTALL_POLICY_BLOCKED, + UTF8ToUTF16(extension->name()), + UTF8ToUTF16(extension->id())); + } + return false; +} + +} // namespace + +namespace extensions { +namespace admin_policy { + +bool BlacklistedByDefault(const base::ListValue* blacklist) { + base::StringValue wildcard("*"); + return blacklist && blacklist->Find(wildcard) != blacklist->end(); +} + +bool UserMayLoad(const base::ListValue* blacklist, + const base::ListValue* whitelist, + const base::DictionaryValue* forcelist, + const base::ListValue* allowed_types, + const Extension* extension, + string16* error) { + // Component extensions are always allowed. + if (extension->location() == Manifest::COMPONENT) + return true; + + // Forced installed extensions cannot be overwritten manually. + if (extension->location() != Manifest::EXTERNAL_POLICY && + extension->location() != Manifest::EXTERNAL_POLICY_DOWNLOAD && + forcelist && forcelist->HasKey(extension->id())) { + return ReturnLoadError(extension, error); + } + + // Early exit for the common case of no policy restrictions. + if ((!blacklist || blacklist->empty()) && (!allowed_types)) + return true; + + // Check whether the extension type is allowed. + // + // If you get a compile error here saying that the type you added is not + // handled by the switch statement below, please consider whether enterprise + // policy should be able to disallow extensions of the new type. If so, add a + // branch to the second block and add a line to the definition of + // kExtensionAllowedTypesMap in configuration_policy_handler_list.cc. + switch (extension->GetType()) { + case Manifest::TYPE_UNKNOWN: + break; + case Manifest::TYPE_EXTENSION: + case Manifest::TYPE_THEME: + case Manifest::TYPE_USER_SCRIPT: + case Manifest::TYPE_HOSTED_APP: + case Manifest::TYPE_LEGACY_PACKAGED_APP: + case Manifest::TYPE_PLATFORM_APP: + case Manifest::TYPE_SHARED_MODULE: + base::FundamentalValue type_value(extension->GetType()); + if (allowed_types && + allowed_types->Find(type_value) == allowed_types->end()) + return ReturnLoadError(extension, error); + break; + } + + // Check the whitelist/forcelist first. + base::StringValue id_value(extension->id()); + if ((whitelist && whitelist->Find(id_value) != whitelist->end()) || + (forcelist && forcelist->HasKey(extension->id()))) + return true; + + // Then check the admin blacklist. + if ((blacklist && blacklist->Find(id_value) != blacklist->end()) || + BlacklistedByDefault(blacklist)) + return ReturnLoadError(extension, error); + + return true; +} + +bool UserMayModifySettings(const Extension* extension, string16* error) { + return ManagementPolicyImpl(extension, error, true); +} + +bool MustRemainEnabled(const Extension* extension, string16* error) { + return ManagementPolicyImpl(extension, error, false); +} + +} // namespace admin_policy +} // namespace extensions diff --git a/extensions/browser/admin_policy.h b/extensions/browser/admin_policy.h new file mode 100644 index 0000000..ea32ee7 --- /dev/null +++ b/extensions/browser/admin_policy.h @@ -0,0 +1,42 @@ +// Copyright 2013 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. + +#ifndef EXTENSIONS_BROWSER_ADMIN_POLICY_H_ +#define EXTENSIONS_BROWSER_ADMIN_POLICY_H_ + +#include "base/values.h" + +namespace extensions { + +class Extension; + +// Functions for providing information about the extension whitelist, +// blacklist, and forcelist imposed by admin policy. +namespace admin_policy { + +// Checks if extensions are blacklisted by default, by policy. When true, this +// means that even extensions without an ID should be blacklisted (e.g. +// from the command line, or when loaded as an unpacked extension). +bool BlacklistedByDefault(const base::ListValue* blacklist); + +// Returns true if the extension is allowed by the admin policy. +bool UserMayLoad(const base::ListValue* blacklist, + const base::ListValue* whitelist, + const base::DictionaryValue* forcelist, + const base::ListValue* allowed_types, + const Extension* extension, + string16* error); + +// Returns false if the extension is required to remain running. In practice +// this enforces the admin policy forcelist. +bool UserMayModifySettings(const Extension* extension, string16* error); + +// Returns false if the extension is required to remain running. In practice +// this enforces the admin policy forcelist. +bool MustRemainEnabled(const Extension* extension, string16* error); + +} // namespace +} // namespace + +#endif // EXTENSIONS_BROWSER_ADMIN_POLICY_H_ diff --git a/extensions/browser/admin_policy_unittest.cc b/extensions/browser/admin_policy_unittest.cc new file mode 100644 index 0000000..02d606d --- /dev/null +++ b/extensions/browser/admin_policy_unittest.cc @@ -0,0 +1,196 @@ +// Copyright 2013 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 "extensions/browser/admin_policy.h" + +#include "base/values.h" +#include "chrome/common/extensions/extension.h" +#include "extensions/common/manifest.h" +#include "extensions/common/manifest_constants.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::Value; +using extensions::Extension; +using extensions::Manifest; + +namespace ap = extensions::admin_policy; + +class ExtensionAdminPolicyTest : public testing::Test { + public: + void CreateExtension(Manifest::Location location) { + base::DictionaryValue values; + CreateExtensionFromValues(location, &values); + } + + void CreateHostedApp(Manifest::Location location) { + base::DictionaryValue values; + values.Set(extensions::manifest_keys::kWebURLs, new base::ListValue()); + values.SetString(extensions::manifest_keys::kLaunchWebURL, + "http://www.example.com"); + CreateExtensionFromValues(location, &values); + } + + void CreateExtensionFromValues(Manifest::Location location, + base::DictionaryValue* values) { + values->SetString(extensions::manifest_keys::kName, "test"); + values->SetString(extensions::manifest_keys::kVersion, "0.1"); + std::string error; + extension_ = Extension::Create(base::FilePath(), location, *values, + Extension::NO_FLAGS, &error); + ASSERT_TRUE(extension_.get()); + } + + protected: + scoped_refptr<Extension> extension_; +}; + +// Tests the flag value indicating that extensions are blacklisted by default. +TEST_F(ExtensionAdminPolicyTest, BlacklistedByDefault) { + EXPECT_FALSE(ap::BlacklistedByDefault(NULL)); + + base::ListValue blacklist; + blacklist.Append(new base::StringValue("http://www.google.com")); + EXPECT_FALSE(ap::BlacklistedByDefault(&blacklist)); + blacklist.Append(new base::StringValue("*")); + EXPECT_TRUE(ap::BlacklistedByDefault(&blacklist)); + + blacklist.Clear(); + blacklist.Append(new base::StringValue("*")); + EXPECT_TRUE(ap::BlacklistedByDefault(&blacklist)); +} + +// Tests UserMayLoad for required extensions. +TEST_F(ExtensionAdminPolicyTest, UserMayLoadRequired) { + CreateExtension(Manifest::COMPONENT); + EXPECT_TRUE(ap::UserMayLoad(NULL, NULL, NULL, NULL, extension_.get(), NULL)); + string16 error; + EXPECT_TRUE(ap::UserMayLoad(NULL, NULL, NULL, NULL, extension_.get(), + &error)); + EXPECT_TRUE(error.empty()); + + // Required extensions may load even if they're on the blacklist. + base::ListValue blacklist; + blacklist.Append(new base::StringValue(extension_->id())); + EXPECT_TRUE(ap::UserMayLoad(&blacklist, NULL, NULL, NULL, extension_.get(), + NULL)); + + blacklist.Append(new base::StringValue("*")); + EXPECT_TRUE(ap::UserMayLoad(&blacklist, NULL, NULL, NULL, extension_.get(), + NULL)); +} + +// Tests UserMayLoad when no blacklist exists, or it's empty. +TEST_F(ExtensionAdminPolicyTest, UserMayLoadNoBlacklist) { + CreateExtension(Manifest::INTERNAL); + EXPECT_TRUE(ap::UserMayLoad(NULL, NULL, NULL, NULL, extension_.get(), NULL)); + base::ListValue blacklist; + EXPECT_TRUE(ap::UserMayLoad(&blacklist, NULL, NULL, NULL, extension_.get(), + NULL)); + string16 error; + EXPECT_TRUE(ap::UserMayLoad(&blacklist, NULL, NULL, NULL, extension_.get(), + &error)); + EXPECT_TRUE(error.empty()); +} + +// Tests UserMayLoad for an extension on the whitelist. +TEST_F(ExtensionAdminPolicyTest, UserMayLoadWhitelisted) { + CreateExtension(Manifest::INTERNAL); + + base::ListValue whitelist; + whitelist.Append(new base::StringValue(extension_->id())); + EXPECT_TRUE(ap::UserMayLoad(NULL, &whitelist, NULL, NULL, extension_.get(), + NULL)); + + base::ListValue blacklist; + blacklist.Append(new base::StringValue(extension_->id())); + EXPECT_TRUE(ap::UserMayLoad(NULL, &whitelist, NULL, NULL, extension_.get(), + NULL)); + string16 error; + EXPECT_TRUE(ap::UserMayLoad(NULL, &whitelist, NULL, NULL, extension_.get(), + &error)); + EXPECT_TRUE(error.empty()); +} + +// Tests UserMayLoad for an extension on the blacklist. +TEST_F(ExtensionAdminPolicyTest, UserMayLoadBlacklisted) { + CreateExtension(Manifest::INTERNAL); + + // Blacklisted by default. + base::ListValue blacklist; + blacklist.Append(new base::StringValue("*")); + EXPECT_FALSE(ap::UserMayLoad(&blacklist, NULL, NULL, NULL, extension_.get(), + NULL)); + string16 error; + EXPECT_FALSE(ap::UserMayLoad(&blacklist, NULL, NULL, NULL, extension_.get(), + &error)); + EXPECT_FALSE(error.empty()); + + // Extension on the blacklist, with and without wildcard. + blacklist.Append(new base::StringValue(extension_->id())); + EXPECT_FALSE(ap::UserMayLoad(&blacklist, NULL, NULL, NULL, extension_.get(), + NULL)); + blacklist.Clear(); + blacklist.Append(new base::StringValue(extension_->id())); + EXPECT_FALSE(ap::UserMayLoad(&blacklist, NULL, NULL, NULL, extension_.get(), + NULL)); + + // With a whitelist. There's no such thing as a whitelist wildcard. + base::ListValue whitelist; + whitelist.Append( + new base::StringValue("behllobkkfkfnphdnhnkndlbkcpglgmj")); + EXPECT_FALSE(ap::UserMayLoad(&blacklist, &whitelist, NULL, NULL, + extension_.get(), NULL)); + whitelist.Append(new base::StringValue("*")); + EXPECT_FALSE(ap::UserMayLoad(&blacklist, &whitelist, NULL, NULL, + extension_.get(), NULL)); +} + +TEST_F(ExtensionAdminPolicyTest, UserMayLoadAllowedTypes) { + CreateExtension(Manifest::INTERNAL); + EXPECT_TRUE(ap::UserMayLoad(NULL, NULL, NULL, NULL, extension_.get(), NULL)); + + base::ListValue allowed_types; + EXPECT_FALSE(ap::UserMayLoad(NULL, NULL, NULL, &allowed_types, + extension_.get(), NULL)); + + allowed_types.AppendInteger(Manifest::TYPE_EXTENSION); + EXPECT_TRUE(ap::UserMayLoad(NULL, NULL, NULL, &allowed_types, + extension_.get(), NULL)); + + CreateHostedApp(Manifest::INTERNAL); + EXPECT_FALSE(ap::UserMayLoad(NULL, NULL, NULL, &allowed_types, + extension_.get(), NULL)); + + CreateHostedApp(Manifest::EXTERNAL_POLICY_DOWNLOAD); + EXPECT_FALSE(ap::UserMayLoad(NULL, NULL, NULL, &allowed_types, + extension_.get(), NULL)); +} + +TEST_F(ExtensionAdminPolicyTest, UserMayModifySettings) { + CreateExtension(Manifest::INTERNAL); + EXPECT_TRUE(ap::UserMayModifySettings(extension_.get(), NULL)); + string16 error; + EXPECT_TRUE(ap::UserMayModifySettings(extension_.get(), &error)); + EXPECT_TRUE(error.empty()); + + CreateExtension(Manifest::EXTERNAL_POLICY_DOWNLOAD); + error.clear(); + EXPECT_FALSE(ap::UserMayModifySettings(extension_.get(), NULL)); + EXPECT_FALSE(ap::UserMayModifySettings(extension_.get(), &error)); + EXPECT_FALSE(error.empty()); +} + +TEST_F(ExtensionAdminPolicyTest, MustRemainEnabled) { + CreateExtension(Manifest::EXTERNAL_POLICY_DOWNLOAD); + EXPECT_TRUE(ap::MustRemainEnabled(extension_.get(), NULL)); + string16 error; + EXPECT_TRUE(ap::MustRemainEnabled(extension_.get(), &error)); + EXPECT_FALSE(error.empty()); + + CreateExtension(Manifest::INTERNAL); + error.clear(); + EXPECT_FALSE(ap::MustRemainEnabled(extension_.get(), NULL)); + EXPECT_FALSE(ap::MustRemainEnabled(extension_.get(), &error)); + EXPECT_TRUE(error.empty()); +} diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp index 98d502d..6cef0ee 100644 --- a/extensions/extensions.gyp +++ b/extensions/extensions.gyp @@ -130,8 +130,11 @@ 'include_dirs': [ '..', '<(INTERMEDIATE_DIR)', + '<(SHARED_INTERMEDIATE_DIR)/chrome', ], 'sources': [ + 'browser/admin_policy.cc', + 'browser/admin_policy.h', 'browser/extension_prefs_scope.h', 'browser/extension_error.cc', 'browser/extension_error.h', |