Bug 1891340 - Part 1: Add parameters to customize the before and after icon tints...
[gecko.git] / ipc / glue / ProcessUtils_common.cpp
blob8fccce586203bdd7b6916d66203f874315b6361e
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ProcessUtils.h"
9 #include "mozilla/Preferences.h"
10 #include "mozilla/GeckoArgs.h"
11 #include "mozilla/dom/RemoteType.h"
12 #include "mozilla/ipc/GeckoChildProcessHost.h"
13 #include "mozilla/UniquePtrExtensions.h"
14 #include "nsPrintfCString.h"
16 #include "XPCSelfHostedShmem.h"
18 namespace mozilla {
19 namespace ipc {
21 SharedPreferenceSerializer::SharedPreferenceSerializer()
22 : mPrefMapSize(0), mPrefsLength(0) {
23 MOZ_COUNT_CTOR(SharedPreferenceSerializer);
26 SharedPreferenceSerializer::~SharedPreferenceSerializer() {
27 MOZ_COUNT_DTOR(SharedPreferenceSerializer);
30 SharedPreferenceSerializer::SharedPreferenceSerializer(
31 SharedPreferenceSerializer&& aOther)
32 : mPrefMapSize(aOther.mPrefMapSize),
33 mPrefsLength(aOther.mPrefsLength),
34 mPrefMapHandle(std::move(aOther.mPrefMapHandle)),
35 mPrefsHandle(std::move(aOther.mPrefsHandle)) {
36 MOZ_COUNT_CTOR(SharedPreferenceSerializer);
39 bool SharedPreferenceSerializer::SerializeToSharedMemory(
40 const GeckoProcessType aDestinationProcessType,
41 const nsACString& aDestinationRemoteType) {
42 mPrefMapHandle =
43 Preferences::EnsureSnapshot(&mPrefMapSize).TakePlatformHandle();
45 bool destIsWebContent =
46 aDestinationProcessType == GeckoProcessType_Content &&
47 (StringBeginsWith(aDestinationRemoteType, WEB_REMOTE_TYPE) ||
48 StringBeginsWith(aDestinationRemoteType, PREALLOC_REMOTE_TYPE));
50 // Serialize the early prefs.
51 nsAutoCStringN<1024> prefs;
52 Preferences::SerializePreferences(prefs, destIsWebContent);
53 mPrefsLength = prefs.Length();
55 base::SharedMemory shm;
56 // Set up the shared memory.
57 if (!shm.Create(prefs.Length())) {
58 NS_ERROR("failed to create shared memory in the parent");
59 return false;
61 if (!shm.Map(prefs.Length())) {
62 NS_ERROR("failed to map shared memory in the parent");
63 return false;
66 // Copy the serialized prefs into the shared memory.
67 memcpy(static_cast<char*>(shm.memory()), prefs.get(), mPrefsLength);
69 mPrefsHandle = shm.TakeHandle();
70 return true;
73 void SharedPreferenceSerializer::AddSharedPrefCmdLineArgs(
74 mozilla::ipc::GeckoChildProcessHost& procHost,
75 std::vector<std::string>& aExtraOpts) const {
76 #if defined(XP_WIN)
77 // Record the handle as to-be-shared, and pass it via a command flag. This
78 // works because Windows handles are system-wide.
79 procHost.AddHandleToShare(GetPrefsHandle().get());
80 procHost.AddHandleToShare(GetPrefMapHandle().get());
81 geckoargs::sPrefsHandle.Put((uintptr_t)(GetPrefsHandle().get()), aExtraOpts);
82 geckoargs::sPrefMapHandle.Put((uintptr_t)(GetPrefMapHandle().get()),
83 aExtraOpts);
84 #else
85 // In contrast, Unix fds are per-process. So remap the fd to a fixed one that
86 // will be used in the child.
87 // XXX: bug 1440207 is about improving how fixed fds are used.
89 // Note: on Android, AddFdToRemap() sets up the fd to be passed via a Parcel,
90 // and the fixed fd isn't used. However, we still need to mark it for
91 // remapping so it doesn't get closed in the child.
92 procHost.AddFdToRemap(GetPrefsHandle().get(), kPrefsFileDescriptor);
93 procHost.AddFdToRemap(GetPrefMapHandle().get(), kPrefMapFileDescriptor);
94 #endif
96 // Pass the lengths via command line flags.
97 geckoargs::sPrefsLen.Put((uintptr_t)(GetPrefsLength()), aExtraOpts);
98 geckoargs::sPrefMapSize.Put((uintptr_t)(GetPrefMapSize()), aExtraOpts);
101 #if defined(ANDROID) || defined(XP_IOS)
102 static int gPrefsFd = -1;
103 static int gPrefMapFd = -1;
105 void SetPrefsFd(int aFd) { gPrefsFd = aFd; }
107 void SetPrefMapFd(int aFd) { gPrefMapFd = aFd; }
108 #endif
110 SharedPreferenceDeserializer::SharedPreferenceDeserializer() {
111 MOZ_COUNT_CTOR(SharedPreferenceDeserializer);
114 SharedPreferenceDeserializer::~SharedPreferenceDeserializer() {
115 MOZ_COUNT_DTOR(SharedPreferenceDeserializer);
118 bool SharedPreferenceDeserializer::DeserializeFromSharedMemory(
119 uint64_t aPrefsHandle, uint64_t aPrefMapHandle, uint64_t aPrefsLen,
120 uint64_t aPrefMapSize) {
121 Maybe<base::SharedMemoryHandle> prefsHandle;
123 #ifdef XP_WIN
124 prefsHandle = Some(UniqueFileHandle(HANDLE((uintptr_t)(aPrefsHandle))));
125 if (!aPrefsHandle) {
126 return false;
129 FileDescriptor::UniquePlatformHandle handle(
130 HANDLE((uintptr_t)(aPrefMapHandle)));
131 if (!aPrefMapHandle) {
132 return false;
135 mPrefMapHandle.emplace(std::move(handle));
136 #endif
138 mPrefsLen = Some((uintptr_t)(aPrefsLen));
139 if (!aPrefsLen) {
140 return false;
143 mPrefMapSize = Some((uintptr_t)(aPrefMapSize));
144 if (!aPrefMapSize) {
145 return false;
148 #if defined(ANDROID) || defined(XP_IOS)
149 // Android/iOS is different; get the FD via gPrefsFd instead of a fixed fd.
150 MOZ_RELEASE_ASSERT(gPrefsFd != -1);
151 prefsHandle = Some(UniqueFileHandle(gPrefsFd));
153 mPrefMapHandle.emplace(UniqueFileHandle(gPrefMapFd));
154 #elif XP_UNIX
155 prefsHandle = Some(UniqueFileHandle(kPrefsFileDescriptor));
157 mPrefMapHandle.emplace(UniqueFileHandle(kPrefMapFileDescriptor));
158 #endif
160 if (prefsHandle.isNothing() || mPrefsLen.isNothing() ||
161 mPrefMapHandle.isNothing() || mPrefMapSize.isNothing()) {
162 return false;
165 // Init the shared-memory base preference mapping first, so that only changed
166 // preferences wind up in heap memory.
167 Preferences::InitSnapshot(mPrefMapHandle.ref(), *mPrefMapSize);
169 // Set up early prefs from the shared memory.
170 if (!mShmem.SetHandle(std::move(*prefsHandle), /* read_only */ true)) {
171 NS_ERROR("failed to open shared memory in the child");
172 return false;
174 if (!mShmem.Map(*mPrefsLen)) {
175 NS_ERROR("failed to map shared memory in the child");
176 return false;
178 Preferences::DeserializePreferences(static_cast<char*>(mShmem.memory()),
179 *mPrefsLen);
181 return true;
184 const FileDescriptor& SharedPreferenceDeserializer::GetPrefMapHandle() const {
185 MOZ_ASSERT(mPrefMapHandle.isSome());
187 return mPrefMapHandle.ref();
190 #ifdef XP_UNIX
191 // On Unix, file descriptors are per-process. This value is used when mapping
192 // a parent process handle to a content process handle.
193 static const int kJSInitFileDescriptor = 11;
194 #endif
196 void ExportSharedJSInit(mozilla::ipc::GeckoChildProcessHost& procHost,
197 std::vector<std::string>& aExtraOpts) {
198 #if defined(ANDROID) || defined(XP_IOS)
199 // The code to support Android/iOS is added in a follow-up patch.
200 return;
201 #else
202 auto& shmem = xpc::SelfHostedShmem::GetSingleton();
203 const mozilla::UniqueFileHandle& uniqHandle = shmem.Handle();
204 size_t len = shmem.Content().Length();
206 // If the file is not found or the content is empty, then we would start the
207 // content process without this optimization.
208 if (!uniqHandle || !len) {
209 return;
212 mozilla::detail::FileHandleType handle = uniqHandle.get();
213 // command line: [-jsInitHandle handle] -jsInitLen length
214 # if defined(XP_WIN)
215 // Record the handle as to-be-shared, and pass it via a command flag.
216 procHost.AddHandleToShare(HANDLE(handle));
217 geckoargs::sJsInitHandle.Put((uintptr_t)(HANDLE(handle)), aExtraOpts);
218 # else
219 // In contrast, Unix fds are per-process. So remap the fd to a fixed one that
220 // will be used in the child.
221 // XXX: bug 1440207 is about improving how fixed fds are used.
223 // Note: on Android, AddFdToRemap() sets up the fd to be passed via a Parcel,
224 // and the fixed fd isn't used. However, we still need to mark it for
225 // remapping so it doesn't get closed in the child.
226 procHost.AddFdToRemap(handle, kJSInitFileDescriptor);
227 # endif
229 // Pass the lengths via command line flags.
230 geckoargs::sJsInitLen.Put((uintptr_t)(len), aExtraOpts);
231 #endif
234 bool ImportSharedJSInit(uint64_t aJsInitHandle, uint64_t aJsInitLen) {
235 // This is an optimization, and as such we can safely recover if the command
236 // line argument are not provided.
237 if (!aJsInitLen) {
238 return true;
241 #ifdef XP_WIN
242 if (!aJsInitHandle) {
243 return true;
245 #endif
247 #ifdef XP_WIN
248 base::SharedMemoryHandle handle(HANDLE((uintptr_t)(aJsInitHandle)));
249 if (!aJsInitHandle) {
250 return false;
252 #endif
254 size_t len = (uintptr_t)(aJsInitLen);
255 if (!aJsInitLen) {
256 return false;
259 #ifdef XP_UNIX
260 auto handle = UniqueFileHandle(kJSInitFileDescriptor);
261 #endif
263 // Initialize the shared memory with the file handle and size of the content
264 // of the self-hosted Xdr.
265 auto& shmem = xpc::SelfHostedShmem::GetSingleton();
266 if (!shmem.InitFromChild(std::move(handle), len)) {
267 NS_ERROR("failed to open shared memory in the child");
268 return false;
271 return true;
274 } // namespace ipc
275 } // namespace mozilla