1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_prompt_actions_win.h"
6
7 #include <algorithm>
8 #include <string>
9 #include <utility>
10
11 #include "base/check.h"
12 #include "base/feature_list.h"
13 #include "base/stl_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_scanner_results_win.h"
17 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h"
18 #include "components/crx_file/id_util.h"
19 #include "extensions/browser/extension_registry.h"
20 #include "extensions/browser/uninstall_reason.h"
21
22 namespace safe_browsing {
23
ChromePromptActions(extensions::ExtensionService * extension_service,extensions::ExtensionRegistry * extension_registry,PromptUserCallback on_prompt_user)24 ChromePromptActions::ChromePromptActions(
25 extensions::ExtensionService* extension_service,
26 extensions::ExtensionRegistry* extension_registry,
27 PromptUserCallback on_prompt_user)
28 : extension_service_(extension_service),
29 extension_registry_(extension_registry),
30 on_prompt_user_(std::move(on_prompt_user)) {
31 DCHECK(on_prompt_user_);
32 }
33
~ChromePromptActions()34 ChromePromptActions::~ChromePromptActions() {}
35
PromptUser(const std::vector<base::FilePath> & files_to_delete,const base::Optional<std::vector<base::string16>> & registry_keys,const base::Optional<std::vector<base::string16>> & extension_ids,PromptUserReplyCallback callback)36 void ChromePromptActions::PromptUser(
37 const std::vector<base::FilePath>& files_to_delete,
38 const base::Optional<std::vector<base::string16>>& registry_keys,
39 const base::Optional<std::vector<base::string16>>& extension_ids,
40 PromptUserReplyCallback callback) {
41 using FileCollection = ChromeCleanerScannerResults::FileCollection;
42 using RegistryKeyCollection =
43 ChromeCleanerScannerResults::RegistryKeyCollection;
44 using ExtensionCollection = ChromeCleanerScannerResults::ExtensionCollection;
45
46 DCHECK(on_prompt_user_);
47 if (base::FeatureList::IsEnabled(kChromeCleanupExtensionsFeature) &&
48 extension_ids) {
49 extension_ids_ = extension_ids.value();
50 } else {
51 extension_ids_.clear();
52 }
53
54 ChromeCleanerScannerResults scanner_results(
55 FileCollection(files_to_delete.begin(), files_to_delete.end()),
56 registry_keys
57 ? RegistryKeyCollection(registry_keys->begin(), registry_keys->end())
58 : RegistryKeyCollection(),
59 extension_ids_.empty()
60 ? ExtensionCollection()
61 : ExtensionCollection(extension_ids_.begin(), extension_ids_.end()));
62
63 std::move(on_prompt_user_)
64 .Run(std::move(scanner_results), std::move(callback));
65 }
66
67 // The |extensions_ids| passed to this function are a subset of the
68 // |extension_ids| passed to PromptUser because the extensions are not all
69 // disabled at the same time.
DisableExtensions(const std::vector<base::string16> & extension_ids)70 bool ChromePromptActions::DisableExtensions(
71 const std::vector<base::string16>& extension_ids) {
72 if (extension_service_ == nullptr || extension_ids_.empty()) {
73 return false;
74 }
75 // Clear the stored extension_ids by moving it onto this stack frame,
76 // so subsequent calls will fail.
77 std::vector<base::string16> verified_extension_ids{};
78 extension_ids_.swap(verified_extension_ids);
79 bool ids_are_valid = std::all_of(
80 extension_ids.begin(), extension_ids.end(),
81 [this, &verified_extension_ids](const base::string16& id) {
82 std::string id_utf8 = base::UTF16ToUTF8(id);
83 return crx_file::id_util::IdIsValid(id_utf8) &&
84 base::Contains(verified_extension_ids, id) &&
85 extension_registry_->GetInstalledExtension(id_utf8) != nullptr;
86 });
87 if (!ids_are_valid) {
88 return false;
89 }
90
91 // This only uninstalls extensions that have been displayed to the user on
92 // the cleanup page.
93 extensions::UninstallReason reason =
94 extensions::UNINSTALL_REASON_USER_INITIATED;
95 bool result = true;
96 for (const base::string16& extension_id : extension_ids) {
97 result = extension_service_->UninstallExtension(
98 base::UTF16ToUTF8(extension_id), reason, nullptr) &&
99 result;
100 }
101 return result;
102 }
103
104 } // namespace safe_browsing
105