blob: 7054d274fb3d88626ed99108ece08ce5a4ac4d86 [file]
// Copyright 2018 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/parsers/shortcut_parser/broker/sandboxed_shortcut_parser.h"
#include <stdio.h>
#include "base/bind.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/strings/string16.h"
#include "base/task/post_task.h"
#include "base/win/scoped_handle.h"
#include "chrome/chrome_cleaner/interfaces/parser_interface.mojom.h"
#include "chrome/chrome_cleaner/parsers/parser_utils/parse_tasks_remaining_counter.h"
#include "mojo/public/cpp/system/platform_handle.h"
namespace chrome_cleaner {
SandboxedShortcutParser::SandboxedShortcutParser(
MojoTaskRunner* mojo_task_runner,
mojom::ParserPtr* parser_ptr)
: mojo_task_runner_(mojo_task_runner), parser_ptr_(parser_ptr) {}
void SandboxedShortcutParser::ParseShortcut(
base::win::ScopedHandle shortcut_handle,
mojom::Parser::ParseShortcutCallback callback) {
mojo_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
[](mojom::ParserPtr* parser_ptr, mojo::ScopedHandle handle,
mojom::Parser::ParseShortcutCallback callback) {
(*parser_ptr)
->ParseShortcut(std::move(handle), std::move(callback));
},
parser_ptr_, mojo::WrapPlatformFile(shortcut_handle.Take()),
std::move(callback)));
}
void SandboxedShortcutParser::FindAndParseChromeShortcutsInFoldersAsync(
const std::vector<base::FilePath>& folders,
const FilePathSet& chrome_exe_locations,
ShortcutsParsingDoneCallback callback) {
base::PostTaskWithTraits(
FROM_HERE, {base::MayBlock(), base::WithBaseSyncPrimitives()},
base::BindOnce(
&SandboxedShortcutParser::FindAndParseChromeShortcutsInFolders,
base::Unretained(this), folders, chrome_exe_locations,
std::move(callback)));
}
void SandboxedShortcutParser::FindAndParseChromeShortcutsInFolders(
const std::vector<base::FilePath>& folders,
const FilePathSet& chrome_exe_locations,
ShortcutsParsingDoneCallback callback) {
if (folders.empty()) {
std::move(callback).Run({});
return;
}
std::vector<base::FilePath> enumerated_shortcuts;
for (const auto& folder : folders) {
if (base::DirectoryExists(folder)) {
base::FileEnumerator lnk_enumerator(folder, /*recursive=*/false,
base::FileEnumerator::FileType::FILES,
L"*.lnk");
base::FilePath lnk_path = lnk_enumerator.Next();
while (!lnk_path.empty()) {
enumerated_shortcuts.push_back(lnk_path);
lnk_path = lnk_enumerator.Next();
}
}
}
if (enumerated_shortcuts.size() == 0) {
std::move(callback).Run({});
return;
}
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
scoped_refptr<ParseTasksRemainingCounter> counter =
base::MakeRefCounted<ParseTasksRemainingCounter>(
enumerated_shortcuts.size(), &event);
std::vector<ShortcutInformation> parsed_shortcuts;
for (const auto& lnk_path : enumerated_shortcuts) {
base::File lnk_file(
lnk_path, base::File::Flags::FLAG_OPEN | base::File::Flags::FLAG_READ);
ParseShortcut(
base::win::ScopedHandle(lnk_file.TakePlatformFile()),
base::BindOnce(&SandboxedShortcutParser::OnShortcutsParsingDone,
base::Unretained(this), chrome_exe_locations, lnk_path,
counter, &parsed_shortcuts));
}
event.Wait();
std::move(callback).Run(parsed_shortcuts);
}
void SandboxedShortcutParser::OnShortcutsParsingDone(
const FilePathSet& chrome_exe_locations,
const base::FilePath& lnk_path,
scoped_refptr<ParseTasksRemainingCounter> counter,
std::vector<ShortcutInformation>* found_shortcuts,
mojom::LnkParsingResult parsing_result,
const base::Optional<base::string16>& optional_file_path,
const base::Optional<base::string16>& optional_command_line_arguments,
const base::Optional<base::string16>& optional_icon_location) {
ShortcutInformation parsed_shortcut;
parsed_shortcut.lnk_path = lnk_path;
if (parsing_result == mojom::LnkParsingResult::SUCCESS) {
if (optional_file_path.has_value())
parsed_shortcut.target_path = optional_file_path.value();
if (optional_command_line_arguments.has_value()) {
parsed_shortcut.command_line_arguments =
optional_command_line_arguments.value();
}
if (optional_icon_location.has_value())
parsed_shortcut.icon_location = optional_icon_location.value();
const base::string16 kChromeLnkName = L"Google Chrome.lnk";
if (chrome_exe_locations.Contains(
base::FilePath(parsed_shortcut.icon_location)) ||
lnk_path.BaseName().value() == kChromeLnkName) {
base::AutoLock lock(lock_);
found_shortcuts->push_back(parsed_shortcut);
}
}
{
base::AutoLock lock(lock_);
counter->Decrement();
}
}
} // namespace chrome_cleaner