Commit 4a2bdd5f authored by Swapnil's avatar Swapnil Committed by Commit Bot

Extending known misconfiguration failures occurred in case of

force installed extensions

When force installed extensions failed to install with failure reason
CRX_INSTALL_ERROR_DECLINED and CrxInstallErrorDetail is
DISALLOWED_BY_POLICY and installation fails because extension type
is not allowed as per the policy ExtensionAllowedTypes, we consider it
as one of the misconfigurations.


Bug: 981891
Change-Id: If4c23d05ab8ba9f29189179e244eaa715733836d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2007646Reviewed-by: default avatarOleg Davydov <burunduk@chromium.org>
Reviewed-by: default avatarKaran Bhatia <karandeepb@chromium.org>
Commit-Queue: Swapnil Gupta <swapnilgupta@google.com>
Cr-Commit-Position: refs/heads/master@{#748236}
parent 3ea08bec
...@@ -1005,6 +1005,11 @@ void CrxInstaller::NotifyCrxInstallComplete( ...@@ -1005,6 +1005,11 @@ void CrxInstaller::NotifyCrxInstallComplete(
if (!success && (!expected_id_.empty() || extension())) { if (!success && (!expected_id_.empty() || extension())) {
switch (error->type()) { switch (error->type()) {
case CrxInstallErrorType::DECLINED: case CrxInstallErrorType::DECLINED:
if (error->detail() == CrxInstallErrorDetail::DISALLOWED_BY_POLICY) {
installation_reporter
->ReportExtensionTypeForPolicyDisallowedExtension(
extension_id, extension()->GetType());
}
installation_reporter->ReportCrxInstallError( installation_reporter->ReportCrxInstallError(
extension_id, extension_id,
InstallationReporter::FailureReason::CRX_INSTALL_ERROR_DECLINED, InstallationReporter::FailureReason::CRX_INSTALL_ERROR_DECLINED,
......
...@@ -110,13 +110,18 @@ void InstallationReporter::ReportFailure(const ExtensionId& id, ...@@ -110,13 +110,18 @@ void InstallationReporter::ReportFailure(const ExtensionId& id,
NotifyObserversOfFailure(id, reason, data); NotifyObserversOfFailure(id, reason, data);
} }
void InstallationReporter::ReportExtensionTypeForPolicyDisallowedExtension(
const ExtensionId& id,
Manifest::Type extension_type) {
InstallationData& data = installation_data_map_[id];
data.extension_type = extension_type;
}
void InstallationReporter::ReportCrxInstallError( void InstallationReporter::ReportCrxInstallError(
const ExtensionId& id, const ExtensionId& id,
FailureReason reason, FailureReason reason,
CrxInstallErrorDetail crx_install_error) { CrxInstallErrorDetail crx_install_error) {
DCHECK(reason == FailureReason::CRX_INSTALL_ERROR_DECLINED || DCHECK(reason == FailureReason::CRX_INSTALL_ERROR_DECLINED ||
reason ==
FailureReason::CRX_INSTALL_ERROR_SANDBOXED_UNPACKER_FAILURE ||
reason == FailureReason::CRX_INSTALL_ERROR_OTHER); reason == FailureReason::CRX_INSTALL_ERROR_OTHER);
InstallationData& data = installation_data_map_[id]; InstallationData& data = installation_data_map_[id];
data.failure_reason = reason; data.failure_reason = reason;
......
...@@ -199,6 +199,9 @@ class InstallationReporter : public KeyedService { ...@@ -199,6 +199,9 @@ class InstallationReporter : public KeyedService {
// CRX_INSTALL_ERROR_SANDBOXED_UNPACKER_FAILURE. // CRX_INSTALL_ERROR_SANDBOXED_UNPACKER_FAILURE.
base::Optional<extensions::SandboxedUnpackerFailureReason> base::Optional<extensions::SandboxedUnpackerFailureReason>
unpacker_failure_reason; unpacker_failure_reason;
// Type of extension, assigned when CRX installation error detail is
// DISALLOWED_BY_POLICY.
base::Optional<Manifest::Type> extension_type;
}; };
class Observer : public base::CheckedObserver { class Observer : public base::CheckedObserver {
...@@ -235,6 +238,11 @@ class InstallationReporter : public KeyedService { ...@@ -235,6 +238,11 @@ class InstallationReporter : public KeyedService {
void ReportDownloadingCacheStatus( void ReportDownloadingCacheStatus(
const ExtensionId& id, const ExtensionId& id,
ExtensionDownloaderDelegate::CacheStatus cache_status); ExtensionDownloaderDelegate::CacheStatus cache_status);
// Assigns the extension type. See InstallationData::extension_type for more
// details.
void ReportExtensionTypeForPolicyDisallowedExtension(
const ExtensionId& id,
Manifest::Type extension_type);
void ReportCrxInstallError(const ExtensionId& id, void ReportCrxInstallError(const ExtensionId& id,
FailureReason reason, FailureReason reason,
CrxInstallErrorDetail crx_install_error); CrxInstallErrorDetail crx_install_error);
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/extensions/extension_management.h"
#include "chrome/browser/extensions/extension_management_constants.h"
#include "chrome/browser/extensions/external_provider_impl.h" #include "chrome/browser/extensions/external_provider_impl.h"
#include "chrome/browser/extensions/forced_extensions/installation_reporter.h" #include "chrome/browser/extensions/forced_extensions/installation_reporter.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
...@@ -198,6 +200,24 @@ void InstallationTracker::OnExtensionInstallationFailed( ...@@ -198,6 +200,24 @@ void InstallationTracker::OnExtensionInstallationFailed(
ReportResults(); ReportResults();
} }
bool InstallationTracker::IsMisconfiguration(
const InstallationReporter::InstallationData& installation_data,
const ExtensionId& id) {
ExtensionManagement* management =
ExtensionManagementFactory::GetForBrowserContext(profile_);
CrxInstallErrorDetail detail = installation_data.install_error_detail.value();
if (detail == CrxInstallErrorDetail::KIOSK_MODE_ONLY)
return true;
if (detail == CrxInstallErrorDetail::DISALLOWED_BY_POLICY &&
!management->IsAllowedManifestType(
installation_data.extension_type.value(), id)) {
return true;
}
return false;
}
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
// Returns the type of session in case extension fails to install. // Returns the type of session in case extension fails to install.
InstallationTracker::SessionType InstallationTracker::GetSessionType() { InstallationTracker::SessionType InstallationTracker::GetSessionType() {
...@@ -329,8 +349,7 @@ void InstallationTracker::ReportMetrics() { ...@@ -329,8 +349,7 @@ void InstallationTracker::ReportMetrics() {
if (installation.install_error_detail) { if (installation.install_error_detail) {
CrxInstallErrorDetail detail = CrxInstallErrorDetail detail =
installation.install_error_detail.value(); installation.install_error_detail.value();
// KIOSK_MODE_ONLY is a type of misconfiguration failure. if (IsMisconfiguration(installation, extension_id))
if (detail == CrxInstallErrorDetail::KIOSK_MODE_ONLY)
misconfigured_extensions++; misconfigured_extensions++;
UMA_HISTOGRAM_ENUMERATION( UMA_HISTOGRAM_ENUMERATION(
"Extensions.ForceInstalledFailureCrxInstallError", detail); "Extensions.ForceInstalledFailureCrxInstallError", detail);
...@@ -349,6 +368,7 @@ void InstallationTracker::ReportMetrics() { ...@@ -349,6 +368,7 @@ void InstallationTracker::ReportMetrics() {
"ForceInstalledSessionsWithNonMisconfigurationFailureOccured", "ForceInstalledSessionsWithNonMisconfigurationFailureOccured",
non_misconfigured_failure_occurred); non_misconfigured_failure_occurred);
} }
void InstallationTracker::ReportResults() { void InstallationTracker::ReportResults() {
DCHECK(!reported_); DCHECK(!reported_);
// Report only if there was non-empty list of force-installed extensions. // Report only if there was non-empty list of force-installed extensions.
......
...@@ -114,6 +114,13 @@ class InstallationTracker : public ExtensionRegistryObserver, ...@@ -114,6 +114,13 @@ class InstallationTracker : public ExtensionRegistryObserver,
// Loads list of force-installed extensions if available. // Loads list of force-installed extensions if available.
void OnForcedExtensionsPrefChanged(); void OnForcedExtensionsPrefChanged();
// Returns true only in case of some well-known misconfigurations which are
// easy to detect. Can return false for misconfigurations which are hard to
// distinguish with other errors.
bool IsMisconfiguration(
const InstallationReporter::InstallationData& installation_data,
const ExtensionId& id);
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
// Returns Session Type in case extension fails to install. // Returns Session Type in case extension fails to install.
SessionType GetSessionType(); SessionType GetSessionType();
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "extensions/browser/pref_names.h" #include "extensions/browser/pref_names.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h" #include "extensions/common/extension_builder.h"
#include "extensions/common/manifest.h"
#include "extensions/common/value_builder.h" #include "extensions/common/value_builder.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -30,8 +31,10 @@ ...@@ -30,8 +31,10 @@
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
namespace { namespace {
constexpr char kExtensionId1[] = "id1";
constexpr char kExtensionId2[] = "id2"; // The extension ids used here should be valid extension ids.
constexpr char kExtensionId1[] = "abcdefghijklmnopabcdefghijklmnop";
constexpr char kExtensionId2[] = "bcdefghijklmnopabcdefghijklmnopa";
constexpr char kExtensionName1[] = "name1"; constexpr char kExtensionName1[] = "name1";
constexpr char kExtensionName2[] = "name2"; constexpr char kExtensionName2[] = "name2";
constexpr char kExtensionUpdateUrl[] = constexpr char kExtensionUpdateUrl[] =
...@@ -396,11 +399,11 @@ TEST_F(ForcedExtensionsInstallationTrackerTest, ExtensionManifestFetchFailed) { ...@@ -396,11 +399,11 @@ TEST_F(ForcedExtensionsInstallationTrackerTest, ExtensionManifestFetchFailed) {
} }
// Session in which either all the extensions installed successfully, or all // Session in which either all the extensions installed successfully, or all
// failures are admin-side misconfigurations. Misconfiguration failure includes // failures are admin-side misconfigurations. This test verifies that failure
// error KIOSK_MODE_ONLY, when force installed extension fails to install with // CRX_INSTALL_ERROR with detailed error KIOSK_MODE_ONLY is considered as
// failure reason CRX_INSTALL_ERROR. // misconfiguration.
TEST_F(ForcedExtensionsInstallationTrackerTest, TEST_F(ForcedExtensionsInstallationTrackerTest,
NonMisconfigurationFailureNotPresent) { NonMisconfigurationFailureNotPresentKioskModeOnlyError) {
SetupForceList(); SetupForceList();
auto extension = auto extension =
ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build();
...@@ -416,6 +419,68 @@ TEST_F(ForcedExtensionsInstallationTrackerTest, ...@@ -416,6 +419,68 @@ TEST_F(ForcedExtensionsInstallationTrackerTest,
1); 1);
} }
// Session in which either all the extensions installed successfully, or all
// failures are admin-side misconfigurations. This test verifies that failure
// CRX_INSTALL_ERROR with detailed error DISALLOWED_BY_POLICY and when extension
// type which is not allowed to install according to policy
// kExtensionAllowedTypes is considered as misconfiguration.
TEST_F(ForcedExtensionsInstallationTrackerTest,
NonMisconfigurationFailureNotPresentDisallowedByPolicyTypeError) {
SetupForceList();
// Set TYPE_EXTENSION and TYPE_THEME as the allowed extension types.
std::unique_ptr<base::Value> list =
ListBuilder().Append("extension").Append("theme").Build();
prefs_->SetManagedPref(pref_names::kAllowedTypes, std::move(list));
auto extension =
ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build();
tracker_->OnExtensionLoaded(&profile_, extension.get());
// Hosted app is not a valid extension type, so this should report an error.
installation_reporter_->ReportExtensionTypeForPolicyDisallowedExtension(
kExtensionId2, Manifest::Type::TYPE_HOSTED_APP);
installation_reporter_->ReportCrxInstallError(
kExtensionId2,
InstallationReporter::FailureReason::CRX_INSTALL_ERROR_DECLINED,
CrxInstallErrorDetail::DISALLOWED_BY_POLICY);
// InstallationTracker shuts down timer because all extension are either
// loaded or failed.
EXPECT_FALSE(fake_timer_->IsRunning());
histogram_tester_.ExpectBucketCount(
kPossibleNonMisconfigurationFailures,
0 /*Misconfiguration failure not present*/, 1 /*Count of the sample*/);
}
// Session in which at least one non misconfiguration failure occurred. One of
// the extension fails to install with DISALLOWED_BY_POLICY error but has
// extension type which is allowed by policy ExtensionAllowedTypes. This is not
// a misconfiguration failure.
TEST_F(ForcedExtensionsInstallationTrackerTest,
NonMisconfigurationFailurePresentDisallowedByPolicyError) {
SetupForceList();
// Set TYPE_EXTENSION and TYPE_THEME as the allowed extension types.
std::unique_ptr<base::Value> list =
ListBuilder().Append("extension").Append("theme").Build();
prefs_->SetManagedPref(pref_names::kAllowedTypes, std::move(list));
auto extension =
ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build();
tracker_->OnExtensionLoaded(&profile_, extension.get());
installation_reporter_->ReportExtensionTypeForPolicyDisallowedExtension(
kExtensionId2, Manifest::Type::TYPE_EXTENSION);
installation_reporter_->ReportCrxInstallError(
kExtensionId2,
InstallationReporter::FailureReason::CRX_INSTALL_ERROR_DECLINED,
CrxInstallErrorDetail::DISALLOWED_BY_POLICY);
// InstallationTracker shuts down timer because all extension are either
// loaded or failed.
EXPECT_FALSE(fake_timer_->IsRunning());
histogram_tester_.ExpectBucketCount(kPossibleNonMisconfigurationFailures,
1 /*Misconfiguration failure present*/,
1 /*Count of the sample*/);
}
// Session in which at least one non misconfiguration failure occurred. // Session in which at least one non misconfiguration failure occurred.
// Misconfiguration failure includes error KIOSK_MODE_ONLY, when force installed // Misconfiguration failure includes error KIOSK_MODE_ONLY, when force installed
// extension fails to install with failure reason CRX_INSTALL_ERROR. // extension fails to install with failure reason CRX_INSTALL_ERROR.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment