Commit 4ced1fac authored by Joe Mason's avatar Joe Mason Committed by Commit Bot

Update chrome_cleaner dirs from internal repo: chrome_utils, crash, logging

Get changes from the internal repo since last branch point:
- chrome_utils now uses the sandboxed JsonParser to parse extension install methods
- add JsonParser sandbox to crash client and process information logging
- get internal API keys for official build, dummy API keys for public build
- Add FOUND_IN_PROGRAMFILES trace location

R=csharp

Bug: 830892
Change-Id: I33944eaaf31be836ac4c91041fd7e4e0d25278d2
Reviewed-on: https://chromium-review.googlesource.com/1195798Reviewed-by: default avatarChris Sharp <csharp@chromium.org>
Commit-Queue: Joe Mason <joenotcharles@chromium.org>
Cr-Commit-Position: refs/heads/master@{#587700}
parent 21e06c68
# 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.
declare_args() {
# If this is true, builds an official release of the Chrome Cleanup Tool
# (requires extra Google-internal resources).
is_official_chrome_cleaner_build = false
}
......@@ -22,7 +22,9 @@ source_set("extensions_util_lib") {
]
deps = [
":chrome_util_lib",
"//base:base",
"//chrome/chrome_cleaner/json_parser",
"//chrome/chrome_cleaner/os:common_os",
]
}
......@@ -35,12 +37,10 @@ source_set("unittest_sources") {
]
deps = [
":chrome_util_lib",
":extensions_util_lib",
"//base:base",
"//base/test:test_support",
"//chrome/chrome_cleaner/constants:common_strings",
"//chrome/chrome_cleaner/os:common_os",
"//chrome/chrome_cleaner/json_parser",
"//chrome/chrome_cleaner/test:test_util",
"//testing/gtest",
]
......
......@@ -79,4 +79,42 @@ bool RetrieveChromeExePathFromCommandLine(base::FilePath* chrome_exe_path) {
return true;
}
void ListChromeExePaths(std::set<base::FilePath>* paths) {
DCHECK(paths);
static const unsigned int install_paths[] = {
base::DIR_PROGRAM_FILESX86, base::DIR_PROGRAM_FILES,
base::DIR_LOCAL_APP_DATA,
};
for (unsigned int path : install_paths) {
base::FilePath install_path;
bool success = base::PathService::Get(path, &install_path);
if (!success) {
LOG(ERROR) << "Can't get path from PathService '" << path << "'.";
continue;
}
base::FilePath chrome_path =
install_path.Append(L"google\\chrome\\application");
if (!base::PathExists(chrome_path))
continue;
paths->insert(chrome_path);
}
}
void ListChromeInstallationPaths(std::set<base::FilePath>* paths) {
DCHECK(paths);
std::set<base::FilePath> exe_paths;
ListChromeExePaths(&exe_paths);
for (const base::FilePath& exe_path : exe_paths) {
base::FilePath pattern = exe_path.Append(L"??.*.*.*");
std::vector<base::FilePath> matches;
CollectMatchingPaths(pattern, &matches);
paths->insert(matches.begin(), matches.end());
}
}
} // namespace chrome_cleaner
......@@ -32,6 +32,14 @@ bool RetrieveChromeVersionAndInstalledDomain(base::string16* chrome_version,
// path exists.
bool RetrieveChromeExePathFromCommandLine(base::FilePath* chrome_exe_path);
// Search for all Chrome executable paths, for example
// "C:\Program Files\Google\Chrome\Application".
void ListChromeExePaths(std::set<base::FilePath>* paths);
// Search for all Chrome versioned installation paths, for example
// "C:\Program Files\Google\Chrome\Application\68.0.3440.84".
void ListChromeInstallationPaths(std::set<base::FilePath>* paths);
} // namespace chrome_cleaner
#endif // CHROME_CHROME_CLEANER_CHROME_UTILS_CHROME_UTIL_H_
......@@ -4,30 +4,94 @@
#include "chrome/chrome_cleaner/chrome_utils/extensions_util.h"
#include "base/stl_util.h"
#include <algorithm>
#include <array>
#include <map>
#include <set>
#include <string>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/files/file_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/values.h"
#include "base/win/registry.h"
#include "chrome/chrome_cleaner/chrome_utils/chrome_util.h"
#include "chrome/chrome_cleaner/os/file_path_sanitization.h"
#include "chrome/chrome_cleaner/os/registry.h"
#include "chrome/chrome_cleaner/os/registry_util.h"
#include "chrome/chrome_cleaner/os/system_util.h"
using base::WaitableEvent;
namespace chrome_cleaner {
namespace {
const int kExtensionIdLength = 32;
class ParseTasksRemainingCounter
: public base::RefCountedThreadSafe<ParseTasksRemainingCounter> {
public:
ParseTasksRemainingCounter(int count, WaitableEvent* done)
: count_(count), done_(done) {}
void Increment() {
DCHECK(count_ > 0);
count_++;
}
void Decrement() {
count_--;
if (count_ == 0) {
done_->Signal();
}
}
private:
friend class base::RefCountedThreadSafe<ParseTasksRemainingCounter>;
~ParseTasksRemainingCounter() = default;
int count_;
WaitableEvent* done_;
};
struct RegistryKey {
HKEY hkey;
const wchar_t* path;
};
const RegistryKey extension_forcelist_keys[] = {
{HKEY_LOCAL_MACHINE,
L"software\\policies\\google\\chrome\\ExtensionInstallForcelist"},
{HKEY_CURRENT_USER,
L"software\\policies\\google\\chrome\\ExtensionInstallForcelist"}};
{HKEY_LOCAL_MACHINE, kChromePoliciesForcelistKeyPath},
{HKEY_CURRENT_USER, kChromePoliciesForcelistKeyPath}};
const RegistryKey extension_settings_keys[] = {
{HKEY_LOCAL_MACHINE, kChromePoliciesKeyPath},
{HKEY_CURRENT_USER, kChromePoliciesKeyPath}};
const wchar_t kExtensionSettingsRegistryEntryName[] = L"ExtensionSettings";
const char kExtensionSettingsInstallationModeName[] = "installation_mode";
const char kExtensionSettingsForceInstalledValue[] = "force_installed";
const wchar_t kExternalExtensionsFilePath[] =
L"default_apps\\external_extensions.json";
// Extension IDs that are expected to be in external_extensions.json, or have
// been in past versions, gathered from
// chrome/browser/resources/default_apps/external_extensions.json
constexpr std::array<const base::char16*, 8> default_extension_whitelist = {
L"blpcfgokakmgnkcojhhkbfbldkacnbeo", L"pjkljhegncpnkpknbcohdijeoejaedia",
L"apdfllckaahabafndbhieahigkjlhalf", L"aohghmighlieiainnegkcijnfilokake",
L"aapocclcgogkmnckokdopfmhonfmgoek", L"felcaaldnbdncclmgdcncolpebgiejap",
L"ghbmnnjooekpmoecnnnilnnbdlolhkhi", L"coobgpohoikkiipiblmjeljniedjpjpf"};
const wchar_t kMasterPreferencesFileName[] = L"master_preferences";
void GetForcelistPoliciesForAccessMask(
REGSAM access_mask,
std::vector<ExtensionRegistryPolicy>* policies) {
std::vector<ExtensionPolicyRegistryEntry>* policies) {
for (size_t i = 0; i < base::size(extension_forcelist_keys); ++i) {
base::win::RegistryValueIterator forcelist_it(
extension_forcelist_keys[i].hkey, extension_forcelist_keys[i].path,
......@@ -50,26 +114,260 @@ void GetForcelistPoliciesForAccessMask(
}
}
void GetExtensionSettingsPoliciesFromParsedJson(
const RegistryKey& registry_key,
std::vector<ExtensionPolicyRegistryEntry>* policies,
scoped_refptr<ParseTasksRemainingCounter> counter,
base::Optional<base::Value> json,
const base::Optional<std::string>& error) {
base::ScopedClosureRunner closure(
base::BindOnce(&ParseTasksRemainingCounter::Decrement, counter.get()));
base::DictionaryValue* extension_settings = nullptr;
if (!json.has_value() || !json->is_dict() ||
!json->GetAsDictionary(&extension_settings)) {
LOG(ERROR) << "Could not read JSON from " << registry_key.hkey << "\\"
<< registry_key.path;
if (error.has_value()) {
LOG(ERROR) << "JSON parser error " << error.value();
}
return;
}
for (const auto& entry : *extension_settings) {
const base::string16& extension_id = base::UTF8ToUTF16(entry.first);
const std::unique_ptr<base::Value>& settings_value = entry.second;
if (settings_value->is_dict()) {
base::Value* installation_mode =
settings_value->FindKey(kExtensionSettingsInstallationModeName);
if (installation_mode != nullptr &&
installation_mode->GetString() ==
kExtensionSettingsForceInstalledValue) {
policies->emplace_back(extension_id, registry_key.hkey,
registry_key.path,
kExtensionSettingsRegistryEntryName);
}
}
}
}
void GetExtensionSettingsPoliciesForAccessMask(
REGSAM access_mask,
JsonParserAPI* json_parser,
std::vector<ExtensionPolicyRegistryEntry>* policies,
scoped_refptr<ParseTasksRemainingCounter> counter) {
for (size_t i = 0; i < base::size(extension_settings_keys); ++i) {
RegKeyPath key(extension_settings_keys[i].hkey,
extension_settings_keys[i].path, access_mask);
base::string16 extension_settings;
RegistryError error;
uint32_t type;
ReadRegistryValue(key, kExtensionSettingsRegistryEntryName,
&extension_settings, &type, &error);
if (error != RegistryError::SUCCESS) {
LOG_IF(WARNING, error != RegistryError::VALUE_NOT_FOUND)
<< "Failed to read string registry value: '"
<< extension_settings_keys[i].path << "\\"
<< kExtensionSettingsRegistryEntryName << "', error: '"
<< static_cast<int>(error) << "'.";
continue;
}
counter->Increment();
json_parser->Parse(
base::UTF16ToUTF8(extension_settings),
base::BindOnce(&GetExtensionSettingsPoliciesFromParsedJson,
extension_settings_keys[i], policies, counter));
}
}
void GetDefaultExtensionsFromParsedJson(
const base::FilePath& extensions_file,
std::vector<ExtensionPolicyFile>* policies,
scoped_refptr<ParseTasksRemainingCounter> counter,
base::Optional<base::Value> json,
const base::Optional<std::string>& error) {
base::ScopedClosureRunner closure(
base::BindOnce(&ParseTasksRemainingCounter::Decrement, counter.get()));
base::DictionaryValue* default_extensions = nullptr;
if (!json.has_value() || !json->is_dict() ||
!json->GetAsDictionary(&default_extensions)) {
LOG(ERROR) << "Could not read JSON from " << SanitizePath(extensions_file);
if (error.has_value()) {
LOG(ERROR) << "JSON parser error " << error.value();
}
return;
}
for (const auto& entry : *default_extensions) {
base::string16 extension_id = base::UTF8ToUTF16(entry.first);
if (std::find(default_extension_whitelist.begin(),
default_extension_whitelist.end(),
extension_id) == default_extension_whitelist.end()) {
policies->emplace_back(extension_id, extensions_file);
}
}
}
void GetMasterPreferencesExtensionsFromParsedJson(
const base::FilePath& extensions_file,
std::vector<ExtensionPolicyFile>* policies,
scoped_refptr<ParseTasksRemainingCounter> counter,
base::Optional<base::Value> json,
const base::Optional<std::string>& error) {
base::ScopedClosureRunner closure(
base::BindOnce(&ParseTasksRemainingCounter::Decrement, counter.get()));
base::DictionaryValue* master_preferences = nullptr;
if (!json.has_value() || !json->is_dict() ||
!json->GetAsDictionary(&master_preferences)) {
LOG(ERROR) << "Could not read JSON from " << SanitizePath(extensions_file);
if (error.has_value()) {
LOG(ERROR) << "JSON parser error " << error.value();
}
return;
}
base::Value* extension_settings = master_preferences->FindPathOfType(
{"extensions", "settings"}, base::Value::Type::DICTIONARY);
if (extension_settings == nullptr)
return;
base::DictionaryValue* extension_settings_dictionary;
extension_settings->GetAsDictionary(&extension_settings_dictionary);
for (const auto& entry : *extension_settings_dictionary) {
base::string16 extension_id = base::UTF8ToUTF16(entry.first);
policies->emplace_back(extension_id, extensions_file);
}
}
} // namespace
ExtensionRegistryPolicy::ExtensionRegistryPolicy(
ExtensionPolicyRegistryEntry::ExtensionPolicyRegistryEntry(
const base::string16& extension_id,
HKEY hkey,
const base::string16& path,
const base::string16& name)
: extension_id(extension_id), hkey(hkey), path(path), name(name) {}
ExtensionRegistryPolicy::ExtensionRegistryPolicy(ExtensionRegistryPolicy&&) =
default;
ExtensionPolicyRegistryEntry::ExtensionPolicyRegistryEntry(
ExtensionPolicyRegistryEntry&&) = default;
ExtensionRegistryPolicy& ExtensionRegistryPolicy::operator=(
ExtensionRegistryPolicy&&) = default;
ExtensionPolicyRegistryEntry& ExtensionPolicyRegistryEntry::operator=(
ExtensionPolicyRegistryEntry&&) = default;
ExtensionPolicyFile::ExtensionPolicyFile(const base::string16& extension_id,
const base::FilePath& path)
: extension_id(extension_id), path(path) {}
ExtensionPolicyFile::ExtensionPolicyFile(ExtensionPolicyFile&&) = default;
ExtensionPolicyFile& ExtensionPolicyFile::operator=(ExtensionPolicyFile&&) =
default;
void GetExtensionForcelistRegistryPolicies(
std::vector<ExtensionRegistryPolicy>* policies) {
std::vector<ExtensionPolicyRegistryEntry>* policies) {
GetForcelistPoliciesForAccessMask(KEY_WOW64_32KEY, policies);
if (IsX64Architecture())
GetForcelistPoliciesForAccessMask(KEY_WOW64_64KEY, policies);
}
void GetNonWhitelistedDefaultExtensions(
JsonParserAPI* json_parser,
std::vector<ExtensionPolicyFile>* policies,
base::WaitableEvent* done) {
std::set<base::FilePath> install_paths;
ListChromeInstallationPaths(&install_paths);
std::map<base::FilePath, std::string> files_read;
for (const base::FilePath& folder : install_paths) {
const base::FilePath& extensions_file(
folder.Append(kExternalExtensionsFilePath));
if (!base::PathExists(extensions_file))
continue;
// Read the external_extensions JSON file.
std::string content;
if (!base::ReadFileToString(extensions_file, &content)) {
PLOG(ERROR) << "Failed to read file: " << SanitizePath(extensions_file);
continue;
}
files_read[extensions_file] = content;
}
if (files_read.size() == 0) {
done->Signal();
return;
}
scoped_refptr<ParseTasksRemainingCounter> counter =
base::MakeRefCounted<ParseTasksRemainingCounter>(files_read.size(), done);
for (const auto& file : files_read) {
const base::FilePath& path = file.first;
const std::string& content = file.second;
json_parser->Parse(content,
base::BindOnce(&GetDefaultExtensionsFromParsedJson, path,
policies, counter));
}
}
void GetExtensionSettingsForceInstalledExtensions(
JsonParserAPI* json_parser,
std::vector<ExtensionPolicyRegistryEntry>* policies,
base::WaitableEvent* done) {
// Make a counter with initial count 1 so it doesn't potentially signal until
// after all parse tasks are posted.
scoped_refptr<ParseTasksRemainingCounter> counter =
base::MakeRefCounted<ParseTasksRemainingCounter>(1, done);
GetExtensionSettingsPoliciesForAccessMask(KEY_WOW64_32KEY, json_parser,
policies, counter);
if (IsX64Architecture()) {
GetExtensionSettingsPoliciesForAccessMask(KEY_WOW64_64KEY, json_parser,
policies, counter);
}
// Decrement so that the counter can signal when it hits 0.
counter->Decrement();
}
void GetMasterPreferencesExtensions(JsonParserAPI* json_parser,
std::vector<ExtensionPolicyFile>* policies,
base::WaitableEvent* done) {
std::set<base::FilePath> exe_paths;
ListChromeExePaths(&exe_paths);
std::map<base::FilePath, std::string> files_read;
for (const base::FilePath& path : exe_paths) {
const base::FilePath& master_preferences(
path.Append(kMasterPreferencesFileName));
if (!base::PathExists(master_preferences))
continue;
std::string content;
if (!base::ReadFileToString(master_preferences, &content)) {
PLOG(ERROR) << "Failed to read file: "
<< SanitizePath(master_preferences);
continue;
}
files_read[master_preferences] = content;
}
if (files_read.size() == 0) {
done->Signal();
return;
}
scoped_refptr<ParseTasksRemainingCounter> counter =
base::MakeRefCounted<ParseTasksRemainingCounter>(files_read.size(), done);
for (const auto& file : files_read) {
const base::FilePath& path = file.first;
const std::string& content = file.second;
json_parser->Parse(
content, base::BindOnce(&GetMasterPreferencesExtensionsFromParsedJson,
path, policies, counter));
}
}
} // namespace chrome_cleaner
......@@ -7,31 +7,73 @@
#include <vector>
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/synchronization/waitable_event.h"
#include "chrome/chrome_cleaner/json_parser/json_parser_api.h"
#include "chrome/chrome_cleaner/os/registry_util.h"
namespace chrome_cleaner {
// A registry key that holds some form of policy for |extension_id|.
struct ExtensionRegistryPolicy {
struct ExtensionPolicyRegistryEntry {
base::string16 extension_id;
HKEY hkey;
base::string16 path;
base::string16 name;
ExtensionRegistryPolicy(const base::string16& extension_id,
HKEY hkey,
const base::string16& path,
const base::string16& name);
ExtensionRegistryPolicy(ExtensionRegistryPolicy&&);
ExtensionRegistryPolicy& operator=(ExtensionRegistryPolicy&&);
ExtensionPolicyRegistryEntry(const base::string16& extension_id,
HKEY hkey,
const base::string16& path,
const base::string16& name);
ExtensionPolicyRegistryEntry(ExtensionPolicyRegistryEntry&&);
ExtensionPolicyRegistryEntry& operator=(ExtensionPolicyRegistryEntry&&);
DISALLOW_COPY_AND_ASSIGN(ExtensionRegistryPolicy);
DISALLOW_COPY_AND_ASSIGN(ExtensionPolicyRegistryEntry);
};
// A file that holds some form of policy for |extension_id|.
struct ExtensionPolicyFile {
base::string16 extension_id;
base::FilePath path;
ExtensionPolicyFile(const base::string16& extension_id,
const base::FilePath& path);
ExtensionPolicyFile(ExtensionPolicyFile&&);
ExtensionPolicyFile& operator=(ExtensionPolicyFile&&);
DISALLOW_COPY_AND_ASSIGN(ExtensionPolicyFile);
};
// Find all extension forcelist registry policies and append to |policies|.
void GetExtensionForcelistRegistryPolicies(
std::vector<ExtensionRegistryPolicy>* policies);
std::vector<ExtensionPolicyRegistryEntry>* policies);
// Find non-whitelisted extension IDs in external_extensions.json files, which
// are extensions that will be installed by default on new user profiles. Using
// the input |json_parser| to parse JSON, append found extensions to |policies|.
// Signals |done| when all parse tasks have finished.
void GetNonWhitelistedDefaultExtensions(
JsonParserAPI* json_parser,
std::vector<ExtensionPolicyFile>* policies,
base::WaitableEvent* done);
// Find all extensions whose enterprise policy settings contain
// "installation_mode":"force_installed" and append them to |policies|. Uses the
// input |json_parser| to parse JSON, and signals |done| when all parse tasks
// have finished.
void GetExtensionSettingsForceInstalledExtensions(
JsonParserAPI* json_parser,
std::vector<ExtensionPolicyRegistryEntry>* policies,
base::WaitableEvent* done);
// Find master preferences extensions, which are installed to new user profiles,
// and append them to |policies|. Uses the input |json_parser| to parse JSON,
// and signals |done| when all parse tasks have finished.
void GetMasterPreferencesExtensions(JsonParserAPI* json_parser,
std::vector<ExtensionPolicyFile>* policies,
base::WaitableEvent* done);
} // namespace chrome_cleaner
......
......@@ -6,10 +6,24 @@
#include <vector>
#include "base/base_paths_win.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/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/scoped_path_override.h"
#include "base/test/test_reg_util_win.h"
#include "base/test/test_timeouts.h"
#include "base/win/registry.h"
#include "chrome/chrome_cleaner/json_parser/test_json_parser.h"
#include "chrome/chrome_cleaner/test/test_file_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::WaitableEvent;
namespace chrome_cleaner {
namespace {
......@@ -23,19 +37,88 @@ struct TestRegistryEntry {
};
const TestRegistryEntry extension_forcelist_entries[] = {
{HKEY_LOCAL_MACHINE,
L"software\\policies\\google\\chrome\\ExtensionInstallForcelist", L"test1",
L"ababababcdcdcdcdefefefefghghghgh;https://clients2.google.com/service/"
{HKEY_LOCAL_MACHINE, kChromePoliciesForcelistKeyPath, L"test1",
L"ababababcdcdcdcdefefefefghghghgh;https://test.test/crx"
L"update2/crx"},
{HKEY_CURRENT_USER,
L"software\\policies\\google\\chrome\\ExtensionInstallForcelist", L"test2",
L"aaaabbbbccccddddeeeeffffgggghhhh;https://clients2.google.com/service/"
{HKEY_CURRENT_USER, kChromePoliciesForcelistKeyPath, L"test2",
L"aaaabbbbccccddddeeeeffffgggghhhh;https://test.test/crx"
L"update2/crx"}};
bool ExtensionPolicyFound(
const wchar_t kFakeChromeFolder[] = L"google\\chrome\\application\\42.12.34.56";
const wchar_t kTestExtensionId1[] = L"ababababcdcdcdcdefefefefghghghgh";
const wchar_t kTestExtensionId2[] = L"aaaabbbbccccddddeeeeffffgggghhhh";
const char kDefaultExtensionsJson[] =
R"(
{
"ababababcdcdcdcdefefefefghghghgh" : {
"external_update_url":"https://test.test/crx"
},
"aaaabbbbccccddddeeeeffffgggghhhh" : {
"external_update_url":"https://test.test/crx"
},
// Google Sheets
"aapocclcgogkmnckokdopfmhonfmgoek" : {
"external_update_url":"https://test.test/crx"
},
})";
const char kInvalidDefaultExtensionsJson[] = "{ json: invalid }";
// ExtensionSettings that has two force_installed extensions and two not.
const wchar_t kExtensionSettingsJson[] =
LR"(
{
"ababababcdcdcdcdefefefefghghghgh": {
"installation_mode": "force_installed",
"update_url":"https://test.test/crx"
},
"aaaabbbbccccddddeeeeffffgggghhhh": {
"installation_mode": "force_installed",
"update_url":"https://test.test/crx"
},
"extensionwithinstallmodeblockeda": {
"installation_mode": "blocked",
"update_url":"https://test.test/crx"
},
"extensionwithnosettingsabcdefghi": {}
})";
const TestRegistryEntry extension_settings_entry = {
HKEY_LOCAL_MACHINE, L"software\\policies\\google\\chrome",
L"ExtensionSettings", kExtensionSettingsJson};
const wchar_t kChromeExePath[] = L"google\\chrome\\application";
const wchar_t kMasterPreferencesFileName[] = L"master_preferences";
const char kMasterPreferencesJson[] =
R"(
{
"homepage": "http://dev.chromium.org/",
"extensions": {
"settings": {
"ababababcdcdcdcdefefefefghghghgh": {
"location": 1,
"manifest": {
"name": "Test extension"
}
},
"aaaabbbbccccddddeeeeffffgggghhhh": {
"location": 1,
"manifest": {
"name": "Another one"
}
}
}
}
})";
const char kMasterPreferencesJsonNoExtensions[] =
R"(
{
"homepage": "http://dev.chromium.org/"
})";
bool ExtensionPolicyRegistryEntryFound(
TestRegistryEntry test_entry,
const std::vector<ExtensionRegistryPolicy>& found_policies) {
for (const ExtensionRegistryPolicy& policy : found_policies) {
const std::vector<ExtensionPolicyRegistryEntry>& found_policies) {
for (const ExtensionPolicyRegistryEntry& policy : found_policies) {
base::string16 test_entry_value(test_entry.value);
if (policy.extension_id == test_entry_value.substr(0, kExtensionIdLength) &&
policy.hkey == test_entry.hkey && policy.path == test_entry.path &&
......@@ -61,12 +144,191 @@ TEST(ExtensionsUtilTest, GetExtensionForcelistRegistryPolicies) {
policy_key.WriteValue(policy.name.c_str(), policy.value.c_str()));
}
std::vector<ExtensionRegistryPolicy> policies;
std::vector<ExtensionPolicyRegistryEntry> policies;
GetExtensionForcelistRegistryPolicies(&policies);
for (const TestRegistryEntry& expected_result : extension_forcelist_entries) {
EXPECT_TRUE(ExtensionPolicyFound(expected_result, policies));
EXPECT_TRUE(ExtensionPolicyRegistryEntryFound(expected_result, policies));
}
}
TEST(ExtensionsUtilTest, GetNonWhitelistedDefaultExtensions) {
// Set up a fake default extensions JSON file.
base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES);
base::FilePath program_files_dir;
ASSERT_TRUE(
base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files_dir));
base::FilePath fake_apps_dir(
program_files_dir.Append(kFakeChromeFolder).Append(L"default_apps"));
ASSERT_TRUE(base::CreateDirectoryAndGetError(fake_apps_dir, nullptr));
base::FilePath default_extensions_file =
fake_apps_dir.Append(L"external_extensions.json");
CreateFileWithContent(default_extensions_file, kDefaultExtensionsJson,
sizeof(kDefaultExtensionsJson) - 1);
ASSERT_TRUE(base::PathExists(default_extensions_file));
// Set up an invalid default extensions JSON file
base::ScopedPathOverride program_files_x86_override(
base::DIR_PROGRAM_FILESX86);
ASSERT_TRUE(
base::PathService::Get(base::DIR_PROGRAM_FILESX86, &program_files_dir));
fake_apps_dir =
program_files_dir.Append(kFakeChromeFolder).Append(L"default_apps");
ASSERT_TRUE(base::CreateDirectoryAndGetError(fake_apps_dir, nullptr));
default_extensions_file = fake_apps_dir.Append(L"external_extensions.json");
CreateFileWithContent(default_extensions_file, kInvalidDefaultExtensionsJson,
sizeof(kInvalidDefaultExtensionsJson) - 1);
ASSERT_TRUE(base::PathExists(default_extensions_file));
TestJsonParser json_parser;
std::vector<ExtensionPolicyFile> policies;
base::WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
GetNonWhitelistedDefaultExtensions(&json_parser, &policies, &done);
ASSERT_TRUE(done.TimedWait(TestTimeouts::action_timeout()));
const base::string16 expected_extension_ids[] = {kTestExtensionId1,
kTestExtensionId2};
ASSERT_EQ(base::size(expected_extension_ids), policies.size());
const base::string16 found_extension_ids[] = {policies[0].extension_id,
policies[1].extension_id};
EXPECT_THAT(expected_extension_ids,
::testing::UnorderedElementsAreArray(found_extension_ids));
}
TEST(ExtensionsUtilTest, GetNonWhitelistedDefaultExtensionsNoFilesFound) {
base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES);
base::ScopedPathOverride program_files_x86_override(
base::DIR_PROGRAM_FILESX86);
TestJsonParser json_parser;
std::vector<ExtensionPolicyFile> policies;
base::WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
GetNonWhitelistedDefaultExtensions(&json_parser, &policies, &done);
ASSERT_TRUE(done.TimedWait(TestTimeouts::action_timeout()));
size_t expected_policies_found = 0;
ASSERT_EQ(expected_policies_found, policies.size());
}
TEST(ExtensionsUtilTest, GetExtensionSettingsForceInstalledExtensions) {
registry_util::RegistryOverrideManager registry_override;
registry_override.OverrideRegistry(HKEY_CURRENT_USER);
registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
base::win::RegKey settings_key;
ASSERT_EQ(ERROR_SUCCESS,
settings_key.Create(extension_settings_entry.hkey,
extension_settings_entry.path.c_str(),
KEY_ALL_ACCESS));
DCHECK(settings_key.Valid());
ASSERT_EQ(ERROR_SUCCESS,
settings_key.WriteValue(extension_settings_entry.name.c_str(),
extension_settings_entry.value.c_str()));
TestJsonParser json_parser;
std::vector<ExtensionPolicyRegistryEntry> policies;
base::WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
GetExtensionSettingsForceInstalledExtensions(&json_parser, &policies, &done);
ASSERT_TRUE(done.TimedWait(TestTimeouts::action_timeout()));
// Check that only the two force installed extensions were found
const base::string16 expected_extension_ids[] = {kTestExtensionId1,
kTestExtensionId2};
const base::string16 found_extension_ids[] = {policies[0].extension_id,
policies[1].extension_id};
EXPECT_THAT(expected_extension_ids,
::testing::UnorderedElementsAreArray(found_extension_ids));
// Also check that the collected registry entries match the values in the
// registry.
for (const ExtensionPolicyRegistryEntry& policy : policies) {
EXPECT_EQ(policy.hkey, extension_settings_entry.hkey);
EXPECT_EQ(policy.path, extension_settings_entry.path);
EXPECT_EQ(policy.name, extension_settings_entry.name);
}
}
TEST(ExtensionsUtilTest,
GetExtensionSettingsForceInstalledExtensionsNoneFound) {
registry_util::RegistryOverrideManager registry_override;
registry_override.OverrideRegistry(HKEY_CURRENT_USER);
registry_override.OverrideRegistry(HKEY_LOCAL_MACHINE);
TestJsonParser json_parser;
std::vector<ExtensionPolicyRegistryEntry> policies;
base::WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
GetExtensionSettingsForceInstalledExtensions(&json_parser, &policies, &done);
ASSERT_TRUE(done.TimedWait(TestTimeouts::action_timeout()));
size_t expected_policies_found = 0;
ASSERT_EQ(expected_policies_found, policies.size());
}
TEST(ExtensionsUtilTest, GetMasterPreferencesExtensions) {
// Set up a fake master preferences JSON file.
base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES);
base::FilePath program_files_dir;
ASSERT_TRUE(
base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files_dir));
base::FilePath chrome_dir(program_files_dir.Append(kChromeExePath));
ASSERT_TRUE(base::CreateDirectoryAndGetError(chrome_dir, nullptr));
base::FilePath master_preferences =
chrome_dir.Append(kMasterPreferencesFileName);
CreateFileWithContent(master_preferences, kMasterPreferencesJson,
sizeof(kMasterPreferencesJson) - 1);
ASSERT_TRUE(base::PathExists(master_preferences));
TestJsonParser json_parser;
std::vector<ExtensionPolicyFile> policies;
base::WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
GetMasterPreferencesExtensions(&json_parser, &policies, &done);
ASSERT_TRUE(done.TimedWait(TestTimeouts::action_timeout()));
const base::string16 expected_extension_ids[] = {kTestExtensionId1,
kTestExtensionId2};
ASSERT_EQ(base::size(expected_extension_ids), policies.size());
const base::string16 found_extension_ids[] = {policies[0].extension_id,
policies[1].extension_id};
EXPECT_THAT(expected_extension_ids,
::testing::UnorderedElementsAreArray(found_extension_ids));
}
TEST(ExtensionsUtilTest, GetMasterPreferencesExtensionsNoneFound) {
// Set up a fake master preferences JSON file.
base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES);
base::FilePath program_files_dir;
ASSERT_TRUE(
base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files_dir));
base::FilePath chrome_dir(program_files_dir.Append(kChromeExePath));
ASSERT_TRUE(base::CreateDirectoryAndGetError(chrome_dir, nullptr));
base::FilePath master_preferences =
chrome_dir.Append(kMasterPreferencesFileName);
CreateFileWithContent(master_preferences, kMasterPreferencesJsonNoExtensions,
sizeof(kMasterPreferencesJsonNoExtensions) - 1);
ASSERT_TRUE(base::PathExists(master_preferences));
TestJsonParser json_parser;
std::vector<ExtensionPolicyFile> policies;
base::WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
GetMasterPreferencesExtensions(&json_parser, &policies, &done);
ASSERT_TRUE(done.TimedWait(TestTimeouts::action_timeout()));
size_t expected_policies_found = 0;
ASSERT_EQ(expected_policies_found, policies.size());
}
} // namespace chrome_cleaner
......@@ -195,6 +195,9 @@ bool CrashpadCrashClient::InitializeCrashReporting(Mode mode,
case SandboxType::kEset:
SetCrashKey(kProcessType, "eset");
break;
case SandboxType::kJsonParser:
SetCrashKey(kProcessType, "json_parser");
break;
default:
NOTREACHED();
}
......
......@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//chrome/chrome_cleaner/chrome_cleaner_args.gni")
source_set("scoped_timed_task_logger") {
sources = [
"scoped_timed_task_logger.cc",
......@@ -66,11 +68,20 @@ source_set("logging_definitions") {
]
}
source_set("dummy_api_keys") {
source_set("api_keys_header") {
sources = [
"api_keys.h",
]
}
source_set("dummy_api_keys") {
sources = [
"dummy_api_keys.cc",
]
deps = [
":api_keys_header",
]
}
static_library("cleaner_logging") {
......@@ -84,7 +95,7 @@ static_library("cleaner_logging") {
]
deps = [
":dummy_api_keys",
":api_keys_header",
"//base",
"//chrome/chrome_cleaner/chrome_utils:chrome_util_lib",
"//chrome/chrome_cleaner/constants:chrome_cleanup_tool_branding_header",
......@@ -101,6 +112,12 @@ static_library("cleaner_logging") {
"//components/chrome_cleaner/public/constants:constants",
]
if (is_official_chrome_cleaner_build) {
deps += [ "//chrome_cleaner_internal/logging:api_keys" ]
} else {
deps += [ ":dummy_api_keys" ]
}
public_deps = [
":common",
]
......@@ -113,7 +130,7 @@ static_library("reporter_logging") {
]
deps = [
":dummy_api_keys",
":api_keys_header",
"//base",
"//chrome/chrome_cleaner/chrome_utils:chrome_util_lib",
"//chrome/chrome_cleaner/constants:common_strings",
......@@ -127,6 +144,12 @@ static_library("reporter_logging") {
"//components/chrome_cleaner/public/constants:constants",
]
if (is_official_chrome_cleaner_build) {
deps += [ "//chrome_cleaner_internal/logging:api_keys" ]
} else {
deps += [ ":dummy_api_keys" ]
}
public_deps = [
":common",
]
......
......@@ -192,17 +192,18 @@ message UwS {
FOUND_IN_STARTUP = 1;
FOUND_IN_MEMORY = 2;
FOUND_IN_UNINSTALLSTRING = 3; // Contents of HKEY_LOCAL_MACHINE\SOFTWARE\
// Wow6432Node\Microsoft\Windows\
// CurrentVersion\Uninstall\<SoftwareName>\
// UninstallString
// Wow6432Node\Microsoft\Windows\
// CurrentVersion\Uninstall\<SoftwareName>\
// UninstallString
FOUND_IN_INSTALLLOCATION = 4; // InstallLocation
FOUND_IN_MUICACHE = 5; // HKEY_CLASSES_ROOT\Local Settings\Software\
// Microsoft\Windows\Shell\MuiCache
// Microsoft\Windows\Shell\MuiCache
FOUND_IN_SERVICE = 6; // Services
FOUND_IN_SHELL = 7; // Menu Start, Startup, Desktop
FOUND_IN_SCHEDULED_TASK = 8; // Task scheduler
FOUND_IN_CLSID = 9; // CLSID
FOUND_IN_MODULES = 10; // Loaded modules of a process
FOUND_IN_PROGRAMFILES = 11; // "Program Files" directory
}
repeated TraceLocation trace_locations = 9;
......@@ -244,6 +245,7 @@ message ProcessInformation {
MAIN = 1;
DEPRECATED_SIGNATURE_MATCHER_SANDBOX = 2;
ESET_SANDBOX = 3;
JSON_PARSER_SANDBOX = 4;
}
optional Process process = 1;
......
......@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/i18n.h"
#include "base/win/windows_version.h"
......@@ -27,7 +26,7 @@
namespace chrome_cleaner {
namespace {
// TODO(joenotcharles): refer to the report definition in the "data" section.
// TODO(joenotcharles): Refer to the report definition in the "data" section.
constexpr net::NetworkTrafficAnnotationTag kReporterTrafficAnnotation =
net::DefineNetworkTrafficAnnotation("unwanted_software_report", R"(
semantics {
......
......@@ -250,6 +250,9 @@ ProcessInformation GetProcessInformationProtoObject(
case SandboxType::kEset:
process_info.set_process(ProcessInformation::ESET_SANDBOX);
break;
case SandboxType::kJsonParser:
process_info.set_process(ProcessInformation::JSON_PARSER_SANDBOX);
break;
default:
NOTREACHED() << "Unknown sandbox type " << static_cast<int>(process_type);
}
......
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