blob: 60fbeef229d61ca3af540bc56232bc6c66e1ba41 [file] [log] [blame]
// Copyright 2019 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/chrome_cleaner/engines/controllers/uwe_scanner_wrapper.h"
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "chrome/chrome_cleaner/chrome_utils/force_installed_extension.h"
#include "chrome/chrome_cleaner/constants/uws_id.h"
#include "chrome/chrome_cleaner/pup_data/pup_data.h"
namespace chrome_cleaner {
namespace {
// Calls any_of if the collection is not empty. Otherwise returns true.
template <class InputIterator, class UnaryPredicate>
bool EmptyOrAnyOf(InputIterator first,
InputIterator last,
UnaryPredicate pred) {
if (first == last) {
return true;
}
return std::any_of(first, last, pred);
}
// Determines if the |matcher| matches the |extension|.
// The |matcher| must also have |found_uws| in its |matcher.uws_id()| list.
// At least 1 of the values in each |matcher| fields must equal the value
// in the relevant |extension| field.
bool ExtensionMatchesMatcher(UwSId found_uws,
const UwEMatcher& matcher,
const ForceInstalledExtension& extension) {
return std::any_of(
matcher.uws_id().begin(), matcher.uws_id().end(),
[&extension, &matcher, found_uws](uint32_t id) {
if (id != found_uws) {
return false;
}
UwEMatcher::MatcherCriteria criteria = matcher.criteria();
auto extension_ids = criteria.extension_id();
auto update_urls = criteria.update_url();
auto install_method = criteria.install_method();
return EmptyOrAnyOf(extension_ids.begin(), extension_ids.end(),
[&extension](std::string extension_id) {
return extension_id == extension.id.AsString();
}) &&
EmptyOrAnyOf(update_urls.begin(), update_urls.end(),
[&extension](std::string update_url) {
return update_url == extension.update_url;
}) &&
EmptyOrAnyOf(install_method.begin(), install_method.end(),
[&extension](int install_method) {
return install_method == extension.install_method;
});
});
}
} // namespace
UwEScannerWrapper::UwEScannerWrapper(
std::unique_ptr<Scanner> scanner,
UwEMatchers* matchers,
const std::vector<ForceInstalledExtension>& force_installed_extensions)
: scanner_(std::move(scanner)),
matchers_(matchers),
force_installed_extensions_(std::move(force_installed_extensions)) {
DCHECK(matchers_);
DCHECK(scanner_);
}
UwEScannerWrapper::UwEScannerWrapper(UwEScannerWrapper&& wrapper) = default;
UwEScannerWrapper& UwEScannerWrapper::operator=(UwEScannerWrapper&& other) =
default;
UwEScannerWrapper::~UwEScannerWrapper() {
DCHECK(IsCompletelyDone());
}
bool UwEScannerWrapper::Start(const FoundUwSCallback& found_uws_callback,
DoneCallback done_callback) {
DCHECK(IsCompletelyDone());
DCHECK(found_uws_callback);
DCHECK(done_callback);
found_uws_callback_ = found_uws_callback;
return scanner_->Start(
base::BindRepeating(&UwEScannerWrapper::FindUwE, base::Unretained(this)),
std::move(done_callback));
}
void UwEScannerWrapper::Stop() {
scanner_->Stop();
}
bool UwEScannerWrapper::IsCompletelyDone() const {
return scanner_->IsCompletelyDone();
}
void UwEScannerWrapper::FindUwE(UwSId found_uws) {
base::ScopedClosureRunner runner(
base::BindOnce(found_uws_callback_, found_uws));
if (force_installed_extensions_.empty()) {
return;
}
if (!PUPData::IsKnownPUP(found_uws)) {
return;
}
PUPData::PUP* pup = PUPData::GetPUP(found_uws);
for (const ForceInstalledExtension& extension : force_installed_extensions_) {
// TODO(b/116852553): This check is inefficient and will not scale if we add
// many matchers.
bool matches_any = std::any_of(
matchers_->uwe_matcher().begin(), matchers_->uwe_matcher().end(),
[&extension, found_uws](UwEMatcher matcher) {
return ExtensionMatchesMatcher(found_uws, matcher, extension);
});
if (matches_any) {
pup->matched_extensions.push_back(extension);
}
}
}
} // namespace chrome_cleaner