blob: 5b7c3a01fae5726be6efa0c39e07e02462e3c715 [file] [log] [blame]
// Copyright 2023 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/ui/webui/settings/safety_check_extensions_handler.h"
#include "chrome/browser/extensions/cws_info_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/grit/generated_resources.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_prefs_factory.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension_id.h"
#include "extensions/common/manifest.h"
namespace settings {
namespace {
// `kPrefAcknowledgeSafetyCheckWarning` should mirror the definition in
// chrome/browser/extensions/api/developer_private/developer_private_api.h.
constexpr extensions::PrefMap kPrefAcknowledgeSafetyCheckWarning = {
"ack_safety_check_warning", extensions::PrefType::kBool,
extensions::PrefScope::kExtensionSpecific};
} // namespace
SafetyCheckExtensionsHandler::SafetyCheckExtensionsHandler(Profile* profile)
: profile_(profile) {}
SafetyCheckExtensionsHandler::~SafetyCheckExtensionsHandler() = default;
void SafetyCheckExtensionsHandler::HandleGetNumberOfExtensionsThatNeedReview(
const base::Value::List& args) {
const base::Value& callback_id = args[0];
AllowJavascript();
ResolveJavascriptCallback(callback_id,
base::Value(GetNumberOfExtensionsThatNeedReview()));
}
void SafetyCheckExtensionsHandler::SetCWSInfoServiceForTest(
extensions::CWSInfoService* cws_info_service) {
cws_info_service_ = cws_info_service;
}
int SafetyCheckExtensionsHandler::GetNumberOfExtensionsThatNeedReview() {
int num_extensions_that_need_review = 0;
if (!base::FeatureList::IsEnabled(extensions::kCWSInfoService)) {
return num_extensions_that_need_review;
}
if (cws_info_service_ == nullptr) {
cws_info_service_ = extensions::CWSInfoService::Get(profile_);
}
extensions::ExtensionPrefs* extension_prefs =
extensions::ExtensionPrefsFactory::GetForBrowserContext(profile_);
for (const auto& extension_id : extension_prefs->GetExtensions()) {
const extensions::Extension* extension =
extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
extension_id, extensions::ExtensionRegistry::EVERYTHING);
// Check if the extension is installed by a policy.
if (!extension ||
extensions::Manifest::IsPolicyLocation(extension->location())) {
continue;
}
bool warning_acked = false;
extension_prefs->ReadPrefAsBoolean(
extension->id(), kPrefAcknowledgeSafetyCheckWarning, &warning_acked);
// If the user has previously acknowledged the warning on this
// extension and chosen to keep it, we will not show an additional
// safety hub warning.
if (warning_acked) {
continue;
}
absl::optional<extensions::CWSInfoService::CWSInfo> extension_info =
cws_info_service_->GetCWSInfo(*extension);
if (extension_info.has_value() && extension_info->is_present) {
switch (extension_info->violation_type) {
case extensions::CWSInfoService::CWSViolationType::kMalware:
case extensions::CWSInfoService::CWSViolationType::kPolicy:
num_extensions_that_need_review++;
break;
case extensions::CWSInfoService::CWSViolationType::kNone:
case extensions::CWSInfoService::CWSViolationType::kMinorPolicy:
case extensions::CWSInfoService::CWSViolationType::kUnknown:
if (extension_info->unpublished_long_ago) {
num_extensions_that_need_review++;
}
break;
}
}
}
return num_extensions_that_need_review;
}
void SafetyCheckExtensionsHandler::OnJavascriptAllowed() {}
void SafetyCheckExtensionsHandler::OnJavascriptDisallowed() {}
void SafetyCheckExtensionsHandler::RegisterMessages() {
// Usage of base::Unretained(this) is safe, because web_ui() owns `this` and
// won't release ownership until destruction.
web_ui()->RegisterMessageCallback(
"getNumberOfExtensionsThatNeedReview",
base::BindRepeating(&SafetyCheckExtensionsHandler::
HandleGetNumberOfExtensionsThatNeedReview,
base::Unretained(this)));
}
} // namespace settings