| // Copyright 2012 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/standard_management_policy_provider.h" |
| |
| #include <string> |
| |
| #include "base/logging.h" |
| #include "base/strings/string16.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "chrome/browser/extensions/extension_management.h" |
| #include "extensions/common/extension.h" |
| #include "extensions/common/manifest.h" |
| #include "extensions/strings/grit/extensions_strings.h" |
| #include "ui/base/l10n/l10n_util.h" |
| |
| namespace extensions { |
| |
| namespace { |
| |
| // Returns whether the extension can be modified under admin policy or not, and |
| // fills |error| with corresponding error message if necessary. |
| bool AdminPolicyIsModifiable(const Extension* source_extension, |
| const Extension* extension, |
| base::string16* error) { |
| // Component and force installed extensions can enable/disable all other |
| // extensions including force installed ones (but component are off limits). |
| const bool component_or_force_installed = |
| source_extension && |
| (Manifest::IsComponentLocation(source_extension->location()) || |
| Manifest::IsPolicyLocation(source_extension->location())); |
| |
| bool is_modifiable = true; |
| |
| if (Manifest::IsComponentLocation(extension->location())) |
| is_modifiable = false; |
| if (!component_or_force_installed && |
| Manifest::IsPolicyLocation(extension->location())) { |
| is_modifiable = false; |
| } |
| |
| if (is_modifiable) |
| return true; |
| |
| if (error) { |
| *error = l10n_util::GetStringFUTF16( |
| IDS_EXTENSION_CANT_MODIFY_POLICY_REQUIRED, |
| base::UTF8ToUTF16(extension->name())); |
| } |
| |
| return false; |
| } |
| |
| } // namespace |
| |
| StandardManagementPolicyProvider::StandardManagementPolicyProvider( |
| const ExtensionManagement* settings) |
| : settings_(settings) { |
| } |
| |
| StandardManagementPolicyProvider::~StandardManagementPolicyProvider() { |
| } |
| |
| std::string |
| StandardManagementPolicyProvider::GetDebugPolicyProviderName() const { |
| #if DCHECK_IS_ON() |
| return "extension management policy controlled settings"; |
| #else |
| IMMEDIATE_CRASH(); |
| #endif |
| } |
| |
| bool StandardManagementPolicyProvider::UserMayLoad( |
| const Extension* extension, |
| base::string16* error) const { |
| // Component extensions are always allowed. |
| if (Manifest::IsComponentLocation(extension->location())) |
| return true; |
| |
| // Shared modules are always allowed too: they only contain resources that |
| // are used by other extensions. The extension that depends on the shared |
| // module may be filtered by policy. |
| if (extension->is_shared_module()) |
| return true; |
| |
| // Always allow bookmark apps. The fact that bookmark apps are an extension is |
| // an internal implementation detail and hence they should not be controlled |
| // by extension management policies. See crbug.com/786061. |
| // TODO(calamity): This special case should be removed by removing bookmark |
| // apps from external sources. See crbug.com/788245. |
| if (extension->from_bookmark()) |
| 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 |
| // kAllowedTypesMap in extension_management_constants.h. |
| 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: { |
| if (!settings_->IsAllowedManifestType(extension->GetType(), |
| extension->id())) |
| return ReturnLoadError(extension, error); |
| break; |
| } |
| case Manifest::NUM_LOAD_TYPES: |
| NOTREACHED(); |
| } |
| |
| ExtensionManagement::InstallationMode installation_mode = |
| settings_->GetInstallationMode(extension); |
| if (installation_mode == ExtensionManagement::INSTALLATION_BLOCKED) |
| return ReturnLoadError(extension, error); |
| |
| return true; |
| } |
| |
| bool StandardManagementPolicyProvider::UserMayInstall( |
| const Extension* extension, |
| base::string16* error) const { |
| ExtensionManagement::InstallationMode installation_mode = |
| settings_->GetInstallationMode(extension); |
| |
| // Force-installed extensions cannot be overwritten manually. |
| if (!Manifest::IsPolicyLocation(extension->location()) && |
| installation_mode == ExtensionManagement::INSTALLATION_FORCED) { |
| return ReturnLoadError(extension, error); |
| } |
| |
| return UserMayLoad(extension, error); |
| } |
| |
| bool StandardManagementPolicyProvider::UserMayModifySettings( |
| const Extension* extension, |
| base::string16* error) const { |
| return AdminPolicyIsModifiable(nullptr, extension, error); |
| } |
| |
| bool StandardManagementPolicyProvider::ExtensionMayModifySettings( |
| const Extension* source_extension, |
| const Extension* extension, |
| base::string16* error) const { |
| return AdminPolicyIsModifiable(source_extension, extension, error); |
| } |
| |
| bool StandardManagementPolicyProvider::MustRemainEnabled( |
| const Extension* extension, |
| base::string16* error) const { |
| return !AdminPolicyIsModifiable(nullptr, extension, error); |
| } |
| |
| bool StandardManagementPolicyProvider::MustRemainDisabled( |
| const Extension* extension, |
| disable_reason::DisableReason* reason, |
| base::string16* error) const { |
| std::string required_version; |
| if (!settings_->CheckMinimumVersion(extension, &required_version)) { |
| if (reason) |
| *reason = disable_reason::DISABLE_UPDATE_REQUIRED_BY_POLICY; |
| if (error) { |
| *error = l10n_util::GetStringFUTF16( |
| IDS_EXTENSION_DISABLED_UPDATE_REQUIRED_BY_POLICY, |
| base::UTF8ToUTF16(extension->name()), |
| base::ASCIIToUTF16(required_version)); |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| bool StandardManagementPolicyProvider::MustRemainInstalled( |
| const Extension* extension, |
| base::string16* error) const { |
| ExtensionManagement::InstallationMode mode = |
| settings_->GetInstallationMode(extension); |
| // Disallow removing of recommended extension, to avoid re-install it |
| // again while policy is reload. But disabling of recommended extension is |
| // allowed. |
| if (mode == ExtensionManagement::INSTALLATION_FORCED || |
| mode == ExtensionManagement::INSTALLATION_RECOMMENDED) { |
| if (error) { |
| *error = l10n_util::GetStringFUTF16( |
| IDS_EXTENSION_CANT_UNINSTALL_POLICY_REQUIRED, |
| base::UTF8ToUTF16(extension->name())); |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| bool StandardManagementPolicyProvider::ReturnLoadError( |
| const extensions::Extension* extension, |
| base::string16* error) const { |
| if (error) { |
| *error = l10n_util::GetStringFUTF16( |
| IDS_EXTENSION_CANT_INSTALL_POLICY_BLOCKED, |
| base::UTF8ToUTF16(extension->name()), |
| base::UTF8ToUTF16(extension->id()), |
| base::UTF8ToUTF16(settings_->BlockedInstallMessage(extension->id()))); |
| } |
| return false; |
| } |
| |
| } // namespace extensions |