1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
content / shell / utility / shell_content_utility_client.cc [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/shell/utility/shell_content_utility_client.h"
#include <memory>
#include <utility>
#include "base/command_line.h"
#include "base/containers/span.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/shared_memory_mapping.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/memory/writable_shared_memory_region.h"
#include "base/process/process.h"
#include "base/ranges/algorithm.h"
#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
#include "components/services/storage/test_api/test_api.h"
#include "content/public/child/child_thread.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/pseudonymization_util.h"
#include "content/public/test/test_service.mojom.h"
#include "content/public/utility/utility_thread.h"
#include "content/shell/common/power_monitor_test_impl.h"
#include "mojo/public/cpp/bindings/binder_map.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "mojo/public/cpp/bindings/service_factory.h"
#include "mojo/public/cpp/system/buffer.h"
#include "sandbox/policy/sandbox.h"
#include "services/test/echo/echo_service.h"
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include "content/test/sandbox_status_service.h"
#endif
#if BUILDFLAG(IS_POSIX)
#include "base/file_descriptor_store.h"
#endif
namespace content {
namespace {
class TestUtilityServiceImpl : public mojom::TestService {
public:
explicit TestUtilityServiceImpl(
mojo::PendingReceiver<mojom::TestService> receiver)
: receiver_(this, std::move(receiver)) {}
TestUtilityServiceImpl(const TestUtilityServiceImpl&) = delete;
TestUtilityServiceImpl& operator=(const TestUtilityServiceImpl&) = delete;
~TestUtilityServiceImpl() override = default;
// mojom::TestService implementation:
void DoSomething(DoSomethingCallback callback) override {
std::move(callback).Run();
}
void DoTerminateProcess(DoTerminateProcessCallback callback) override {
base::Process::TerminateCurrentProcessImmediately(0);
}
void DoCrashImmediately(DoCrashImmediatelyCallback callback) override {
base::ImmediateCrash();
}
void CreateFolder(CreateFolderCallback callback) override {
// Note: This is used to check if the sandbox is disabled or not since
// creating a folder is forbidden when it is enabled.
std::move(callback).Run(base::ScopedTempDir().CreateUniqueTempDir());
}
void GetRequestorName(GetRequestorNameCallback callback) override {
NOTREACHED_IN_MIGRATION();
}
void CreateReadOnlySharedMemoryRegion(
const std::string& message,
CreateReadOnlySharedMemoryRegionCallback callback) override {
base::MappedReadOnlyRegion map_and_region =
base::ReadOnlySharedMemoryRegion::Create(message.size());
CHECK(map_and_region.IsValid());
base::ranges::copy(message,
map_and_region.mapping.GetMemoryAsSpan<char>().begin());
std::move(callback).Run(std::move(map_and_region.region));
}
void CreateWritableSharedMemoryRegion(
const std::string& message,
CreateWritableSharedMemoryRegionCallback callback) override {
auto region = base::WritableSharedMemoryRegion::Create(message.size());
CHECK(region.IsValid());
base::WritableSharedMemoryMapping mapping = region.Map();
CHECK(mapping.IsValid());
base::ranges::copy(message, mapping.GetMemoryAsSpan<char>().begin());
std::move(callback).Run(std::move(region));
}
void CreateUnsafeSharedMemoryRegion(
const std::string& message,
CreateUnsafeSharedMemoryRegionCallback callback) override {
auto region = base::UnsafeSharedMemoryRegion::Create(message.size());
CHECK(region.IsValid());
base::WritableSharedMemoryMapping mapping = region.Map();
CHECK(mapping.IsValid());
base::ranges::copy(message, mapping.GetMemoryAsSpan<char>().begin());
std::move(callback).Run(std::move(region));
}
void CloneSharedMemoryContents(
base::ReadOnlySharedMemoryRegion region,
CloneSharedMemoryContentsCallback callback) override {
auto mapping = region.Map();
auto new_region = base::UnsafeSharedMemoryRegion::Create(region.GetSize());
auto new_mapping = new_region.Map();
memcpy(new_mapping.memory(), mapping.memory(), region.GetSize());
std::move(callback).Run(std::move(new_region));
}
void IsProcessSandboxed(IsProcessSandboxedCallback callback) override {
std::move(callback).Run(sandbox::policy::Sandbox::IsProcessSandboxed());
}
void PseudonymizeString(const std::string& value,
PseudonymizeStringCallback callback) override {
std::move(callback).Run(
PseudonymizationUtil::PseudonymizeStringForTesting(value));
}
void PassWriteableFile(base::File file,
PassWriteableFileCallback callback) override {
std::move(callback).Run();
}
void WriteToPreloadedPipe() override {
#if BUILDFLAG(IS_POSIX)
base::MemoryMappedFile::Region region;
base::ScopedFD write_pipe = base::FileDescriptorStore::GetInstance().TakeFD(
mojom::kTestPipeKey, ®ion);
CHECK(write_pipe.is_valid());
CHECK(region == base::MemoryMappedFile::Region::kWholeFile);
CHECK(base::WriteFileDescriptor(write_pipe.get(), "test"));
#else
NOTREACHED_IN_MIGRATION();
#endif
}
private:
mojo::Receiver<mojom::TestService> receiver_;
};
auto RunTestService(mojo::PendingReceiver<mojom::TestService> receiver) {
return std::make_unique<TestUtilityServiceImpl>(std::move(receiver));
}
auto RunEchoService(mojo::PendingReceiver<echo::mojom::EchoService> receiver) {
return std::make_unique<echo::EchoService>(std::move(receiver));
}
} // namespace
ShellContentUtilityClient::ShellContentUtilityClient(bool is_browsertest) {
if (is_browsertest &&
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kProcessType) == switches::kUtilityProcess) {
network_service_test_helper_ = NetworkServiceTestHelper::Create();
audio_service_test_helper_ = std::make_unique<AudioServiceTestHelper>();
storage::InjectTestApiImplementation();
register_sandbox_status_helper_ = true;
}
}
ShellContentUtilityClient::~ShellContentUtilityClient() = default;
void ShellContentUtilityClient::ExposeInterfacesToBrowser(
mojo::BinderMap* binders) {
binders->Add<mojom::PowerMonitorTest>(
base::BindRepeating(&PowerMonitorTestImpl::MakeSelfOwnedReceiver),
base::SingleThreadTaskRunner::GetCurrentDefault());
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
if (register_sandbox_status_helper_) {
binders->Add<content::mojom::SandboxStatusService>(
base::BindRepeating(
&content::SandboxStatusService::MakeSelfOwnedReceiver),
base::SingleThreadTaskRunner::GetCurrentDefault());
}
#endif
}
void ShellContentUtilityClient::RegisterIOThreadServices(
mojo::ServiceFactory& services) {
services.Add(RunTestService);
services.Add(RunEchoService);
}
} // namespace content