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
|
// Copyright 2021 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/omaha_attributes_handler.h"
#include <optional>
#include "base/metrics/histogram_functions.h"
#include "base/values.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/blocklist_extension_prefs.h"
#include "extensions/browser/blocklist_state.h"
#include "extensions/browser/extension_registrar.h"
#include "extensions/browser/extension_registry.h"
namespace extensions {
namespace {
// Logs UMA metrics when an extension is disabled remotely.
void ReportExtensionDisabledRemotely(bool should_be_remotely_disabled,
ExtensionUpdateCheckDataKey reason) {
// Report that the extension is newly disabled due to Omaha attributes.
if (should_be_remotely_disabled) {
base::UmaHistogramEnumeration("Extensions.ExtensionDisabledRemotely2",
reason);
}
// Report that the extension has added a new disable reason.
base::UmaHistogramEnumeration(
"Extensions.ExtensionAddDisabledRemotelyReason2", reason);
}
// Logs UMA metrics when the key is not found in Omaha attributes.
void ReportNoUpdateCheckKeys() {
base::UmaHistogramEnumeration("Extensions.ExtensionDisabledRemotely2",
ExtensionUpdateCheckDataKey::kNoKey);
}
// Logs UMA metrics when a remotely disabled extension is re-enabled.
void ReportReenableExtension(ExtensionUpdateCheckDataKey reason) {
const char* histogram = nullptr;
switch (reason) {
case ExtensionUpdateCheckDataKey::kMalware:
histogram = "Extensions.ExtensionReenabledRemotely";
break;
case ExtensionUpdateCheckDataKey::kPotentiallyUWS:
histogram = "Extensions.ExtensionReenabledRemotelyForPotentiallyUWS";
break;
case ExtensionUpdateCheckDataKey::kPolicyViolation:
histogram = "Extensions.ExtensionReenabledRemotelyForPolicyViolation";
break;
case ExtensionUpdateCheckDataKey::kNoKey:
NOTREACHED();
}
base::UmaHistogramCounts100(histogram, 1);
}
// Checks whether the `state` is in the `attributes`.
bool HasOmahaBlocklistStateInAttributes(const base::Value::Dict& attributes,
BitMapBlocklistState state) {
std::optional<bool> state_value;
switch (state) {
case BitMapBlocklistState::BLOCKLISTED_MALWARE:
state_value = attributes.FindBool("_malware");
break;
case BitMapBlocklistState::BLOCKLISTED_CWS_POLICY_VIOLATION:
state_value = attributes.FindBool("_policy_violation");
break;
case BitMapBlocklistState::BLOCKLISTED_POTENTIALLY_UNWANTED:
state_value = attributes.FindBool("_potentially_uws");
break;
case BitMapBlocklistState::NOT_BLOCKLISTED:
case BitMapBlocklistState::BLOCKLISTED_SECURITY_VULNERABILITY:
NOTREACHED()
<< "The other states are not applicable in Omaha attributes.";
}
return state_value.value_or(false);
}
} // namespace
OmahaAttributesHandler::OmahaAttributesHandler(
ExtensionPrefs* extension_prefs,
ExtensionRegistry* registry,
ExtensionRegistrar* registrar)
: extension_prefs_(extension_prefs),
registry_(registry),
registrar_(registrar) {}
void OmahaAttributesHandler::PerformActionBasedOnOmahaAttributes(
const ExtensionId& extension_id,
const base::Value::Dict& attributes) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// It is possible that an extension is uninstalled when the omaha attributes
// are notified by the update client asynchronously. In this case, we should
// ignore this extension.
if (!registry_->GetInstalledExtension(extension_id)) {
return;
}
HandleMalwareOmahaAttribute(extension_id, attributes);
HandleGreylistOmahaAttribute(
extension_id, attributes,
BitMapBlocklistState::BLOCKLISTED_CWS_POLICY_VIOLATION,
ExtensionUpdateCheckDataKey::kPolicyViolation);
HandleGreylistOmahaAttribute(
extension_id, attributes,
BitMapBlocklistState::BLOCKLISTED_POTENTIALLY_UNWANTED,
ExtensionUpdateCheckDataKey::kPotentiallyUWS);
}
void OmahaAttributesHandler::HandleMalwareOmahaAttribute(
const ExtensionId& extension_id,
const base::Value::Dict& attributes) {
bool has_malware_value = HasOmahaBlocklistStateInAttributes(
attributes, BitMapBlocklistState::BLOCKLISTED_MALWARE);
if (!has_malware_value) {
ReportNoUpdateCheckKeys();
if (!blocklist_prefs::HasOmahaBlocklistState(
extension_id, BitMapBlocklistState::BLOCKLISTED_MALWARE,
extension_prefs_)) {
return;
}
// The extension was previously blocklisted by Omaha, but is no longer.
// Clear the old omaha state.
ReportReenableExtension(ExtensionUpdateCheckDataKey::kMalware);
blocklist_prefs::RemoveOmahaBlocklistState(
extension_id, BitMapBlocklistState::BLOCKLISTED_MALWARE,
extension_prefs_);
registrar_->OnBlocklistStateRemoved(extension_id);
return;
}
if (blocklist_prefs::HasOmahaBlocklistState(
extension_id, BitMapBlocklistState::BLOCKLISTED_MALWARE,
extension_prefs_)) {
// The extension is already disabled. No work needs to be done.
return;
}
ReportExtensionDisabledRemotely(registrar_->IsExtensionEnabled(extension_id),
ExtensionUpdateCheckDataKey::kMalware);
blocklist_prefs::AddOmahaBlocklistState(
extension_id, BitMapBlocklistState::BLOCKLISTED_MALWARE,
extension_prefs_);
registrar_->OnBlocklistStateAdded(extension_id);
}
void OmahaAttributesHandler::HandleGreylistOmahaAttribute(
const ExtensionId& extension_id,
const base::Value::Dict& attributes,
BitMapBlocklistState greylist_state,
ExtensionUpdateCheckDataKey reason) {
bool has_attribute_value =
HasOmahaBlocklistStateInAttributes(attributes, greylist_state);
bool has_omaha_blocklist_state = blocklist_prefs::HasOmahaBlocklistState(
extension_id, greylist_state, extension_prefs_);
if (!has_attribute_value) {
if (has_omaha_blocklist_state) {
blocklist_prefs::RemoveOmahaBlocklistState(extension_id, greylist_state,
extension_prefs_);
ReportReenableExtension(reason);
}
registrar_->OnGreylistStateRemoved(extension_id);
return;
}
ReportExtensionDisabledRemotely(
/*should_be_remotely_disabled=*/!has_omaha_blocklist_state, reason);
blocklist_prefs::AddOmahaBlocklistState(extension_id, greylist_state,
extension_prefs_);
registrar_->OnGreylistStateAdded(extension_id, greylist_state);
}
} // namespace extensions
|