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