1 // Copyright 2019 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 #ifndef CHROME_CHROME_CLEANER_ENGINES_TARGET_SANDBOXED_TEST_HELPERS_H_
6 #define CHROME_CHROME_CLEANER_ENGINES_TARGET_SANDBOXED_TEST_HELPERS_H_
7 
8 #include <memory>
9 #include <utility>
10 #include <vector>
11 
12 #include "base/bind.h"
13 #include "base/callback_helpers.h"
14 #include "base/run_loop.h"
15 #include "chrome/chrome_cleaner/engines/broker/cleaner_engine_requests_impl.h"
16 #include "chrome/chrome_cleaner/engines/broker/engine_cleanup_results_impl.h"
17 #include "chrome/chrome_cleaner/engines/broker/engine_file_requests_impl.h"
18 #include "chrome/chrome_cleaner/engines/broker/engine_requests_impl.h"
19 #include "chrome/chrome_cleaner/engines/broker/engine_scan_results_impl.h"
20 #include "chrome/chrome_cleaner/engines/broker/interface_metadata_observer.h"
21 #include "chrome/chrome_cleaner/engines/common/engine_digest_verifier.h"
22 #include "chrome/chrome_cleaner/engines/target/cleaner_engine_requests_proxy.h"
23 #include "chrome/chrome_cleaner/engines/target/engine_commands_impl.h"
24 #include "chrome/chrome_cleaner/engines/target/engine_file_requests_proxy.h"
25 #include "chrome/chrome_cleaner/engines/target/engine_requests_proxy.h"
26 #include "chrome/chrome_cleaner/ipc/ipc_test_util.h"
27 #include "chrome/chrome_cleaner/mojom/engine_sandbox.mojom.h"
28 #include "chrome/chrome_cleaner/os/file_remover.h"
29 #include "chrome/chrome_cleaner/os/layered_service_provider_wrapper.h"
30 #include "chrome/chrome_cleaner/pup_data/pup_data.h"
31 #include "mojo/public/cpp/bindings/pending_associated_remote.h"
32 #include "mojo/public/cpp/bindings/pending_receiver.h"
33 #include "mojo/public/cpp/bindings/pending_remote.h"
34 #include "mojo/public/cpp/bindings/remote.h"
35 
36 namespace chrome_cleaner {
37 
38 // |BaseClass| should be ParentProcess or SandboxedParentProcess.
39 template <typename BaseClass>
40 class MaybeSandboxedParentProcess : public BaseClass {
41  public:
42   enum class CallbacksToSetup {
43     kFileRequests,
44     kScanAndCleanupRequests,
45     kCleanupRequests
46   };
47 
48   MaybeSandboxedParentProcess(
49       scoped_refptr<MojoTaskRunner> mojo_task_runner,
50       CallbacksToSetup requests_to_setup,
51       InterfaceMetadataObserver* metadata_observer = nullptr)
BaseClass(std::move (mojo_task_runner))52       : BaseClass(std::move(mojo_task_runner)),
53         requests_to_setup_(requests_to_setup),
54         engine_commands_(
55             std::make_unique<mojo::Remote<mojom::EngineCommands>>()),
56         file_requests_impl_(
57             std::make_unique<EngineFileRequestsImpl>(this->mojo_task_runner(),
58                                                      metadata_observer)) {
59     if (requests_to_setup_ == CallbacksToSetup::kScanAndCleanupRequests ||
60         requests_to_setup_ == CallbacksToSetup::kCleanupRequests) {
61       scanner_impl_ = std::make_unique<EngineRequestsImpl>(
62           this->mojo_task_runner(), metadata_observer);
63       scan_results_impl_ =
64           std::make_unique<EngineScanResultsImpl>(metadata_observer);
65     }
66     if (requests_to_setup_ == CallbacksToSetup::kCleanupRequests) {
67       scoped_refptr<chrome_cleaner::DigestVerifier> verifier =
68           GetDigestVerifier();
69       std::unique_ptr<chrome_cleaner::FileRemoverAPI> file_remover =
70           std::make_unique<chrome_cleaner::FileRemover>(
71               verifier, /*archiver=*/nullptr,
72               chrome_cleaner::LayeredServiceProviderWrapper(),
73               base::DoNothing::Repeatedly());
74       cleaner_impl_ = std::make_unique<CleanerEngineRequestsImpl>(
75           this->mojo_task_runner(), metadata_observer, std::move(file_remover));
76       cleanup_results_impl_ =
77           std::make_unique<EngineCleanupResultsImpl>(metadata_observer);
78     }
79   }
80 
81   ~MaybeSandboxedParentProcess() override = default;
82 
83  protected:
CreateImpl(mojo::ScopedMessagePipeHandle mojo_pipe)84   void CreateImpl(mojo::ScopedMessagePipeHandle mojo_pipe) override {
85     engine_commands_->Bind(
86         mojo::PendingRemote<mojom::EngineCommands>(std::move(mojo_pipe), 0));
87 
88     mojo::PendingAssociatedRemote<mojom::EngineFileRequests> file_requests;
89     file_requests_impl_->Bind(&file_requests);
90 
91     // Bind to empty callbacks as we don't care about the result.
92     mojo::PendingAssociatedRemote<mojom::EngineRequests> scanner;
93     mojo::PendingAssociatedRemote<mojom::EngineScanResults> scanner_results;
94     if (requests_to_setup_ == CallbacksToSetup::kScanAndCleanupRequests ||
95         requests_to_setup_ == CallbacksToSetup::kCleanupRequests) {
96       scanner_impl_->Bind(&scanner);
97       scan_results_impl_->BindToCallbacks(
98           &scanner_results,
99           base::BindRepeating(
100               base::DoNothing::Repeatedly<UwSId, const PUPData::PUP&>()),
101           base::BindOnce(base::DoNothing::Once<uint32_t>()));
102     }
103 
104     mojo::PendingAssociatedRemote<mojom::CleanerEngineRequests> cleaner;
105     mojo::PendingAssociatedRemote<mojom::EngineCleanupResults> cleanup_results;
106     if (requests_to_setup_ == CallbacksToSetup::kCleanupRequests) {
107       cleaner_impl_->Bind(&cleaner);
108       cleanup_results_impl_->BindToCallbacks(
109           &cleanup_results, base::BindOnce(base::DoNothing::Once<uint32_t>()));
110     }
111 
112     // Now call the target process to signal that setup is finished.
113     auto operation_started = base::BindOnce([](uint32_t unused_result_code) {});
114     if (requests_to_setup_ == CallbacksToSetup::kFileRequests) {
115       (*engine_commands_)
116           ->Initialize(std::move(file_requests), base::FilePath(),
117                        std::move(operation_started));
118 
119     } else if (requests_to_setup_ ==
120                CallbacksToSetup::kScanAndCleanupRequests) {
121       (*engine_commands_)
122           ->StartScan(/*enabled_uws=*/std::vector<UwSId>{},
123                       /*enabled_locations=*/std::vector<UwS::TraceLocation>{},
124                       /*include_details=*/false, std::move(file_requests),
125                       std::move(scanner), std::move(scanner_results),
126                       std::move(operation_started));
127 
128     } else if (requests_to_setup_ == CallbacksToSetup::kCleanupRequests) {
129       (*engine_commands_)
130           ->StartCleanup(/*enabled_uws=*/std::vector<UwSId>(),
131                          std::move(file_requests), std::move(scanner),
132                          std::move(cleaner), std::move(cleanup_results),
133                          std::move(operation_started));
134     }
135   }
136 
DestroyImpl()137   void DestroyImpl() override {
138     // Reset everything in the reverse order. Reset the associated pointers
139     // first since they will error if they are closed after
140     // |engine_commands_|.
141     cleanup_results_impl_.reset();
142     cleaner_impl_.reset();
143 
144     scan_results_impl_.reset();
145     scanner_impl_.reset();
146 
147     file_requests_impl_.reset();
148     engine_commands_.reset();
149   }
150 
151   CallbacksToSetup requests_to_setup_;
152 
153   std::unique_ptr<mojo::Remote<mojom::EngineCommands>> engine_commands_;
154   std::unique_ptr<EngineFileRequestsImpl> file_requests_impl_;
155 
156   std::unique_ptr<EngineRequestsImpl> scanner_impl_;
157   std::unique_ptr<CleanerEngineRequestsImpl> cleaner_impl_;
158 
159   std::unique_ptr<EngineScanResultsImpl> scan_results_impl_;
160   std::unique_ptr<EngineCleanupResultsImpl> cleanup_results_impl_;
161 };
162 
163 class SandboxChildProcess : public ChildProcess {
164  public:
165   explicit SandboxChildProcess(scoped_refptr<MojoTaskRunner> mojo_task_runner);
166 
167   void BindEngineCommandsReceiver(
168       mojo::PendingReceiver<mojom::EngineCommands> receiver,
169       base::WaitableEvent* event);
170 
171   scoped_refptr<EngineFileRequestsProxy> GetFileRequestsProxy();
172   scoped_refptr<EngineRequestsProxy> GetEngineRequestsProxy();
173   scoped_refptr<CleanerEngineRequestsProxy> GetCleanerEngineRequestsProxy();
174 
175   void UnbindRequestsRemotes();
176 
177   // Exit code value to be used by the child process on connection errors.
178   static const int kConnectionErrorExitCode;
179 
180  protected:
181   ~SandboxChildProcess() override;
182 
183  private:
184   class FakeEngineDelegate;
185 
186   scoped_refptr<FakeEngineDelegate> fake_engine_delegate_;
187   std::unique_ptr<EngineCommandsImpl> engine_commands_impl_;
188 };
189 
190 }  // namespace chrome_cleaner
191 
192 #endif  //  CHROME_CHROME_CLEANER_ENGINES_TARGET_SANDBOXED_TEST_HELPERS_H_
193