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