Line data Source code
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/. */
6 :
7 : #include "mozilla/ipc/IOThreadChild.h"
8 :
9 : #include "ContentProcess.h"
10 : #include "ContentPrefs.h"
11 :
12 : #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
13 : #include <stdlib.h>
14 : #endif
15 :
16 : #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
17 : #include "mozilla/Preferences.h"
18 : #include "mozilla/SandboxSettings.h"
19 : #include "nsAppDirectoryServiceDefs.h"
20 : #include "nsDirectoryService.h"
21 : #include "nsDirectoryServiceDefs.h"
22 : #endif
23 :
24 : using mozilla::ipc::IOThreadChild;
25 :
26 : namespace mozilla {
27 : namespace dom {
28 :
29 : #if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
30 : static bool
31 : IsSandboxTempDirRequired()
32 : {
33 : // On Windows, a sandbox-writable temp directory is only used
34 : // when sandbox pref level >= 1.
35 : return GetEffectiveContentSandboxLevel() >= 1;
36 : }
37 :
38 : static void
39 : SetTmpEnvironmentVariable(nsIFile* aValue)
40 : {
41 : // Save the TMP environment variable so that is is picked up by GetTempPath().
42 : // Note that we specifically write to the TMP variable, as that is the first
43 : // variable that is checked by GetTempPath() to determine its output.
44 : nsAutoString fullTmpPath;
45 : nsresult rv = aValue->GetPath(fullTmpPath);
46 : if (NS_WARN_IF(NS_FAILED(rv))) {
47 : return;
48 : }
49 : Unused << NS_WARN_IF(!SetEnvironmentVariableW(L"TMP", fullTmpPath.get()));
50 : // We also set TEMP in case there is naughty third-party code that is
51 : // referencing the environment variable directly.
52 : Unused << NS_WARN_IF(!SetEnvironmentVariableW(L"TEMP", fullTmpPath.get()));
53 : }
54 : #endif
55 :
56 : #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
57 : static bool
58 : IsSandboxTempDirRequired()
59 : {
60 : // On OSX, use the sandbox-writable temp when the pref level >= 1.
61 : return (GetEffectiveContentSandboxLevel() >= 1);
62 : }
63 :
64 : static void
65 : SetTmpEnvironmentVariable(nsIFile* aValue)
66 : {
67 : nsAutoCString fullTmpPath;
68 : nsresult rv = aValue->GetNativePath(fullTmpPath);
69 : if (NS_WARN_IF(NS_FAILED(rv))) {
70 : return;
71 : }
72 : Unused << NS_WARN_IF(setenv("TMPDIR", fullTmpPath.get(), 1) != 0);
73 : }
74 : #endif
75 :
76 : #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
77 : static void
78 : SetUpSandboxEnvironment()
79 : {
80 : MOZ_ASSERT(nsDirectoryService::gService,
81 : "SetUpSandboxEnvironment relies on nsDirectoryService being initialized");
82 :
83 : if (!IsSandboxTempDirRequired()) {
84 : return;
85 : }
86 :
87 : nsCOMPtr<nsIFile> sandboxedContentTemp;
88 : nsresult rv =
89 : nsDirectoryService::gService->Get(NS_APP_CONTENT_PROCESS_TEMP_DIR,
90 : NS_GET_IID(nsIFile),
91 : getter_AddRefs(sandboxedContentTemp));
92 : if (NS_WARN_IF(NS_FAILED(rv))) {
93 : return;
94 : }
95 :
96 : // Change the gecko defined temp directory to our sandbox-writable one.
97 : // Undefine returns a failure if the property is not already set.
98 : Unused << nsDirectoryService::gService->Undefine(NS_OS_TEMP_DIR);
99 : rv = nsDirectoryService::gService->Set(NS_OS_TEMP_DIR, sandboxedContentTemp);
100 : if (NS_WARN_IF(NS_FAILED(rv))) {
101 : return;
102 : }
103 :
104 : SetTmpEnvironmentVariable(sandboxedContentTemp);
105 : }
106 : #endif
107 :
108 : bool
109 2 : ContentProcess::Init(int aArgc, char* aArgv[])
110 : {
111 : // If passed in grab the application path for xpcom init
112 2 : bool foundAppdir = false;
113 2 : bool foundChildID = false;
114 2 : bool foundIsForBrowser = false;
115 2 : bool foundIntPrefs = false;
116 2 : bool foundBoolPrefs = false;
117 2 : bool foundStringPrefs = false;
118 :
119 : uint64_t childID;
120 : bool isForBrowser;
121 :
122 : #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
123 : // If passed in grab the profile path for sandboxing
124 : bool foundProfile = false;
125 : nsCOMPtr<nsIFile> profileDir;
126 : #endif
127 :
128 4 : InfallibleTArray<PrefSetting> prefsArray;
129 24 : for (int idx = aArgc; idx > 0; idx--) {
130 24 : if (!aArgv[idx]) {
131 0 : continue;
132 : }
133 :
134 24 : if (!strcmp(aArgv[idx], "-appdir")) {
135 2 : MOZ_ASSERT(!foundAppdir);
136 2 : if (foundAppdir) {
137 0 : continue;
138 : }
139 4 : nsCString appDir;
140 2 : appDir.Assign(nsDependentCString(aArgv[idx+1]));
141 2 : mXREEmbed.SetAppDir(appDir);
142 2 : foundAppdir = true;
143 22 : } else if (!strcmp(aArgv[idx], "-childID")) {
144 2 : MOZ_ASSERT(!foundChildID);
145 2 : if (foundChildID) {
146 0 : continue;
147 : }
148 2 : if (idx + 1 < aArgc) {
149 2 : childID = strtoull(aArgv[idx + 1], nullptr, 10);
150 2 : foundChildID = true;
151 : }
152 20 : } else if (!strcmp(aArgv[idx], "-isForBrowser") || !strcmp(aArgv[idx], "-notForBrowser")) {
153 2 : MOZ_ASSERT(!foundIsForBrowser);
154 2 : if (foundIsForBrowser) {
155 0 : continue;
156 : }
157 2 : isForBrowser = strcmp(aArgv[idx], "-notForBrowser");
158 2 : foundIsForBrowser = true;
159 18 : } else if (!strcmp(aArgv[idx], "-intPrefs")) {
160 2 : SET_PREF_PHASE(BEGIN_INIT_PREFS);
161 2 : char* str = aArgv[idx + 1];
162 138 : while (*str) {
163 68 : int32_t index = strtol(str, &str, 10);
164 68 : MOZ_ASSERT(str[0] == ':');
165 68 : str++;
166 136 : MaybePrefValue value(PrefValue(static_cast<int32_t>(strtol(str, &str, 10))));
167 68 : MOZ_ASSERT(str[0] == '|');
168 68 : str++;
169 136 : PrefSetting pref(nsCString(ContentPrefs::GetContentPref(index)), value, MaybePrefValue());
170 68 : prefsArray.AppendElement(pref);
171 : }
172 2 : SET_PREF_PHASE(END_INIT_PREFS);
173 2 : foundIntPrefs = true;
174 16 : } else if (!strcmp(aArgv[idx], "-boolPrefs")) {
175 2 : SET_PREF_PHASE(BEGIN_INIT_PREFS);
176 2 : char* str = aArgv[idx + 1];
177 370 : while (*str) {
178 184 : int32_t index = strtol(str, &str, 10);
179 184 : MOZ_ASSERT(str[0] == ':');
180 184 : str++;
181 368 : MaybePrefValue value(PrefValue(!!strtol(str, &str, 10)));
182 184 : MOZ_ASSERT(str[0] == '|');
183 184 : str++;
184 368 : PrefSetting pref(nsCString(ContentPrefs::GetContentPref(index)), value, MaybePrefValue());
185 184 : prefsArray.AppendElement(pref);
186 : }
187 2 : SET_PREF_PHASE(END_INIT_PREFS);
188 2 : foundBoolPrefs = true;
189 14 : } else if (!strcmp(aArgv[idx], "-stringPrefs")) {
190 2 : SET_PREF_PHASE(BEGIN_INIT_PREFS);
191 2 : char* str = aArgv[idx + 1];
192 18 : while (*str) {
193 8 : int32_t index = strtol(str, &str, 10);
194 8 : MOZ_ASSERT(str[0] == ':');
195 8 : str++;
196 8 : int32_t length = strtol(str, &str, 10);
197 8 : MOZ_ASSERT(str[0] == ';');
198 8 : str++;
199 16 : MaybePrefValue value(PrefValue(nsCString(str, length)));
200 16 : PrefSetting pref(nsCString(ContentPrefs::GetContentPref(index)), value, MaybePrefValue());
201 8 : prefsArray.AppendElement(pref);
202 8 : str += length + 1;
203 8 : MOZ_ASSERT(*(str - 1) == '|');
204 : }
205 2 : SET_PREF_PHASE(END_INIT_PREFS);
206 2 : foundStringPrefs = true;
207 : }
208 12 : else if (!strcmp(aArgv[idx], "-safeMode")) {
209 0 : gSafeMode = true;
210 : }
211 :
212 : #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
213 : else if (!strcmp(aArgv[idx], "-profile")) {
214 : MOZ_ASSERT(!foundProfile);
215 : if (foundProfile) {
216 : continue;
217 : }
218 : bool flag;
219 : nsresult rv = XRE_GetFileFromPath(aArgv[idx+1], getter_AddRefs(profileDir));
220 : if (NS_FAILED(rv) ||
221 : NS_FAILED(profileDir->Exists(&flag)) || !flag) {
222 : NS_WARNING("Invalid profile directory passed to content process.");
223 : profileDir = nullptr;
224 : }
225 : foundProfile = true;
226 : }
227 : #endif /* XP_MACOSX && MOZ_CONTENT_SANDBOX */
228 :
229 24 : bool allFound = foundAppdir && foundChildID && foundIsForBrowser && foundIntPrefs && foundBoolPrefs && foundStringPrefs;
230 :
231 : #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
232 : allFound &= foundProfile;
233 : #endif
234 :
235 24 : if (allFound) {
236 2 : break;
237 : }
238 : }
239 2 : Preferences::SetInitPreferences(&prefsArray);
240 2 : mContent.Init(IOThreadChild::message_loop(),
241 : ParentPid(),
242 : IOThreadChild::channel(),
243 : childID,
244 2 : isForBrowser);
245 2 : mXREEmbed.Start();
246 : #if (defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
247 : mContent.SetProfileDir(profileDir);
248 : #endif
249 :
250 : #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
251 : SetUpSandboxEnvironment();
252 : #endif
253 :
254 4 : return true;
255 : }
256 :
257 : // Note: CleanUp() never gets called in non-debug builds because we exit early
258 : // in ContentChild::ActorDestroy().
259 : void
260 0 : ContentProcess::CleanUp()
261 : {
262 0 : mXREEmbed.Stop();
263 0 : }
264 :
265 : } // namespace dom
266 : } // namespace mozilla
|