Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "nsAppRunner.h"
7 : #include "nsToolkitCompsCID.h"
8 : #include "nsXREDirProvider.h"
9 : #include "mozilla/AddonManagerStartup.h"
10 :
11 : #include "jsapi.h"
12 : #include "xpcpublic.h"
13 :
14 : #include "nsIAddonInterposition.h"
15 : #include "nsIAppStartup.h"
16 : #include "nsIDirectoryEnumerator.h"
17 : #include "nsIFile.h"
18 : #include "nsIObserver.h"
19 : #include "nsIObserverService.h"
20 : #include "nsISimpleEnumerator.h"
21 : #include "nsIToolkitChromeRegistry.h"
22 : #include "nsIToolkitProfileService.h"
23 : #include "nsIXULRuntime.h"
24 :
25 : #include "nsAppDirectoryServiceDefs.h"
26 : #include "nsDirectoryServiceDefs.h"
27 : #include "nsDirectoryServiceUtils.h"
28 : #include "nsXULAppAPI.h"
29 : #include "nsCategoryManagerUtils.h"
30 :
31 : #include "nsDependentString.h"
32 : #include "nsCOMArray.h"
33 : #include "nsArrayEnumerator.h"
34 : #include "nsEnumeratorUtils.h"
35 : #include "nsReadableUtils.h"
36 :
37 : #include "SpecialSystemDirectory.h"
38 :
39 : #include "mozilla/dom/ScriptSettings.h"
40 :
41 : #include "mozilla/Services.h"
42 : #include "mozilla/Omnijar.h"
43 : #include "mozilla/Preferences.h"
44 : #include "mozilla/Telemetry.h"
45 :
46 : #include <stdlib.h>
47 :
48 : #ifdef XP_WIN
49 : #include "city.h"
50 : #include <windows.h>
51 : #include <shlobj.h>
52 : #endif
53 : #ifdef XP_MACOSX
54 : #include "nsILocalFileMac.h"
55 : // for chflags()
56 : #include <sys/stat.h>
57 : #include <unistd.h>
58 : #endif
59 : #ifdef XP_UNIX
60 : #include <ctype.h>
61 : #endif
62 : #ifdef XP_IOS
63 : #include "UIKitDirProvider.h"
64 : #endif
65 :
66 : #if defined(MOZ_CONTENT_SANDBOX)
67 : #include "mozilla/SandboxSettings.h"
68 : #if (defined(XP_WIN) || defined(XP_MACOSX))
69 : #include "nsIUUIDGenerator.h"
70 : #include "mozilla/Unused.h"
71 : #if defined(XP_WIN)
72 : #include "WinUtils.h"
73 : #endif
74 : #endif
75 : #endif
76 :
77 : #if defined(XP_MACOSX)
78 : #define APP_REGISTRY_NAME "Application Registry"
79 : #elif defined(XP_WIN)
80 : #define APP_REGISTRY_NAME "registry.dat"
81 : #else
82 : #define APP_REGISTRY_NAME "appreg"
83 : #endif
84 :
85 : #define PREF_OVERRIDE_DIRNAME "preferences"
86 :
87 : #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
88 : static already_AddRefed<nsIFile> GetContentProcessSandboxTempDir();
89 : static nsresult DeleteDirIfExists(nsIFile *dir);
90 : static bool IsContentSandboxDisabled();
91 : static const char* GetContentProcessTempBaseDirKey();
92 : static already_AddRefed<nsIFile> CreateContentProcessSandboxTempDir();
93 : #endif
94 :
95 : nsXREDirProvider* gDirServiceProvider = nullptr;
96 :
97 3 : nsXREDirProvider::nsXREDirProvider() :
98 3 : mProfileNotified(false)
99 : {
100 3 : gDirServiceProvider = this;
101 3 : }
102 :
103 0 : nsXREDirProvider::~nsXREDirProvider()
104 : {
105 0 : gDirServiceProvider = nullptr;
106 0 : }
107 :
108 : nsXREDirProvider*
109 0 : nsXREDirProvider::GetSingleton()
110 : {
111 0 : return gDirServiceProvider;
112 : }
113 :
114 : nsresult
115 3 : nsXREDirProvider::Initialize(nsIFile *aXULAppDir,
116 : nsIFile *aGREDir,
117 : nsIDirectoryServiceProvider* aAppProvider)
118 : {
119 3 : NS_ENSURE_ARG(aXULAppDir);
120 3 : NS_ENSURE_ARG(aGREDir);
121 :
122 3 : mAppProvider = aAppProvider;
123 3 : mXULAppDir = aXULAppDir;
124 3 : mGREDir = aGREDir;
125 : #if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
126 : // The GRE directory can be used in sandbox rules, so we need to make sure
127 : // it doesn't contain any junction points or symlinks or the sandbox will
128 : // reject those rules.
129 : if (!mozilla::widget::WinUtils::ResolveJunctionPointsAndSymLinks(mGREDir)) {
130 : NS_WARNING("Failed to resolve GRE Dir.");
131 : }
132 : // If the mXULAppDir is different it lives below the mGREDir. To avoid
133 : // confusion resolve that as well even though we don't need it for sandbox
134 : // rules. Some tests rely on this for example.
135 : if (!mozilla::widget::WinUtils::ResolveJunctionPointsAndSymLinks(mXULAppDir)) {
136 : NS_WARNING("Failed to resolve XUL App Dir.");
137 : }
138 : #endif
139 3 : mGREDir->Clone(getter_AddRefs(mGREBinDir));
140 : #ifdef XP_MACOSX
141 : mGREBinDir->SetNativeLeafName(NS_LITERAL_CSTRING("MacOS"));
142 : #endif
143 :
144 3 : if (!mProfileDir) {
145 6 : nsCOMPtr<nsIDirectoryServiceProvider> app(do_QueryInterface(mAppProvider));
146 3 : if (app) {
147 0 : bool per = false;
148 0 : app->GetFile(NS_APP_USER_PROFILE_50_DIR, &per, getter_AddRefs(mProfileDir));
149 0 : NS_ASSERTION(per, "NS_APP_USER_PROFILE_50_DIR must be persistent!");
150 0 : NS_ASSERTION(mProfileDir, "NS_APP_USER_PROFILE_50_DIR not defined! This shouldn't happen!");
151 : }
152 : }
153 :
154 : #ifdef MOZ_B2G
155 : LoadAppBundleDirs();
156 : #endif
157 :
158 3 : return NS_OK;
159 : }
160 :
161 : nsresult
162 1 : nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir)
163 : {
164 1 : NS_ASSERTION(aDir && aLocalDir, "We don't support no-profile apps yet!");
165 :
166 : nsresult rv;
167 :
168 1 : rv = EnsureDirectoryExists(aDir);
169 1 : if (NS_FAILED(rv))
170 0 : return rv;
171 :
172 1 : rv = EnsureDirectoryExists(aLocalDir);
173 1 : if (NS_FAILED(rv))
174 0 : return rv;
175 :
176 : #ifdef XP_MACOSX
177 : bool same;
178 : if (NS_SUCCEEDED(aDir->Equals(aLocalDir, &same)) && !same) {
179 : // Ensure that the cache directory is not indexed by Spotlight
180 : // (bug 718910). At least on OS X, the cache directory (under
181 : // ~/Library/Caches/) is always the "local" user profile
182 : // directory. This is confusing, since *both* user profile
183 : // directories are "local" (they both exist under the user's
184 : // home directory). But this usage dates back at least as far
185 : // as the patch for bug 291033, where "local" seems to mean
186 : // "suitable for temporary storage". Don't hide the cache
187 : // directory if by some chance it and the "non-local" profile
188 : // directory are the same -- there are bad side effects from
189 : // hiding a profile directory under /Library/Application Support/
190 : // (see bug 801883).
191 : nsAutoCString cacheDir;
192 : if (NS_SUCCEEDED(aLocalDir->GetNativePath(cacheDir))) {
193 : if (chflags(cacheDir.get(), UF_HIDDEN)) {
194 : NS_WARNING("Failed to set Cache directory to HIDDEN.");
195 : }
196 : }
197 : }
198 : #endif
199 :
200 1 : mProfileDir = aDir;
201 1 : mProfileLocalDir = aLocalDir;
202 : #if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
203 : // The profile directory can be used in sandbox rules, so we need to make sure
204 : // it doesn't contain any junction points or symlinks or the sandbox will
205 : // reject those rules.
206 : if (!mozilla::widget::WinUtils::ResolveJunctionPointsAndSymLinks(mProfileDir)) {
207 : NS_WARNING("Failed to resolve Profile Dir.");
208 : }
209 : #endif
210 1 : return NS_OK;
211 : }
212 :
213 23 : NS_IMPL_QUERY_INTERFACE(nsXREDirProvider,
214 : nsIDirectoryServiceProvider,
215 : nsIDirectoryServiceProvider2,
216 : nsIProfileStartup)
217 :
218 : NS_IMETHODIMP_(MozExternalRefCountType)
219 26 : nsXREDirProvider::AddRef()
220 : {
221 26 : return 1;
222 : }
223 :
224 : NS_IMETHODIMP_(MozExternalRefCountType)
225 23 : nsXREDirProvider::Release()
226 : {
227 23 : return 0;
228 : }
229 :
230 : nsresult
231 0 : nsXREDirProvider::GetUserProfilesRootDir(nsIFile** aResult,
232 : const nsACString* aProfileName,
233 : const nsACString* aAppName,
234 : const nsACString* aVendorName)
235 : {
236 0 : nsCOMPtr<nsIFile> file;
237 0 : nsresult rv = GetUserDataDirectory(getter_AddRefs(file),
238 : false,
239 0 : aProfileName, aAppName, aVendorName);
240 :
241 0 : if (NS_SUCCEEDED(rv)) {
242 : #if !defined(XP_UNIX) || defined(XP_MACOSX)
243 : rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
244 : #endif
245 : // We must create the profile directory here if it does not exist.
246 0 : nsresult tmp = EnsureDirectoryExists(file);
247 0 : if (NS_FAILED(tmp)) {
248 0 : rv = tmp;
249 : }
250 : }
251 0 : file.swap(*aResult);
252 0 : return rv;
253 : }
254 :
255 : nsresult
256 0 : nsXREDirProvider::GetUserProfilesLocalDir(nsIFile** aResult,
257 : const nsACString* aProfileName,
258 : const nsACString* aAppName,
259 : const nsACString* aVendorName)
260 : {
261 0 : nsCOMPtr<nsIFile> file;
262 0 : nsresult rv = GetUserDataDirectory(getter_AddRefs(file),
263 : true,
264 0 : aProfileName, aAppName, aVendorName);
265 :
266 0 : if (NS_SUCCEEDED(rv)) {
267 : #if !defined(XP_UNIX) || defined(XP_MACOSX)
268 : rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
269 : #endif
270 : // We must create the profile directory here if it does not exist.
271 0 : nsresult tmp = EnsureDirectoryExists(file);
272 0 : if (NS_FAILED(tmp)) {
273 0 : rv = tmp;
274 : }
275 : }
276 0 : file.swap(*aResult);
277 0 : return NS_OK;
278 : }
279 :
280 : #if defined(XP_UNIX) || defined(XP_MACOSX)
281 : /**
282 : * Get the directory that is the parent of the system-wide directories
283 : * for extensions and native-messaing manifests.
284 : *
285 : * On OSX this is /Library/Application Support/Mozilla
286 : * On Linux this is /usr/{lib,lib64}/mozilla
287 : * (for 32- and 64-bit systems respsectively)
288 : */
289 : static nsresult
290 0 : GetSystemParentDirectory(nsIFile** aFile)
291 : {
292 : nsresult rv;
293 0 : nsCOMPtr<nsIFile> localDir;
294 : #if defined(XP_MACOSX)
295 : rv = GetOSXFolderType(kOnSystemDisk, kApplicationSupportFolderType, getter_AddRefs(localDir));
296 : if (NS_SUCCEEDED(rv)) {
297 : rv = localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla"));
298 : }
299 : #else
300 0 : NS_NAMED_LITERAL_CSTRING(dirname,
301 : #ifdef HAVE_USR_LIB64_DIR
302 : "/usr/lib64/mozilla"
303 : #elif defined(__OpenBSD__) || defined(__FreeBSD__)
304 : "/usr/local/lib/mozilla"
305 : #else
306 : "/usr/lib/mozilla"
307 : #endif
308 : );
309 0 : rv = NS_NewNativeLocalFile(dirname, false, getter_AddRefs(localDir));
310 : #endif
311 :
312 0 : if (NS_SUCCEEDED(rv)) {
313 0 : localDir.forget(aFile);
314 : }
315 0 : return rv;
316 : }
317 : #endif
318 :
319 : NS_IMETHODIMP
320 46 : nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
321 : nsIFile** aFile)
322 : {
323 : nsresult rv;
324 :
325 46 : bool gettingProfile = false;
326 :
327 46 : if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) {
328 : // If XRE_NotifyProfile hasn't been called, don't fall through to
329 : // mAppProvider on the profile keys.
330 1 : if (!mProfileNotified)
331 0 : return NS_ERROR_FAILURE;
332 :
333 1 : if (mProfileLocalDir)
334 1 : return mProfileLocalDir->Clone(aFile);
335 :
336 0 : if (mAppProvider)
337 0 : return mAppProvider->GetFile(aProperty, aPersistent, aFile);
338 :
339 : // This falls through to the case below
340 0 : gettingProfile = true;
341 : }
342 45 : if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) || gettingProfile) {
343 4 : if (!mProfileNotified)
344 3 : return NS_ERROR_FAILURE;
345 :
346 1 : if (mProfileDir)
347 1 : return mProfileDir->Clone(aFile);
348 :
349 0 : if (mAppProvider)
350 0 : return mAppProvider->GetFile(aProperty, aPersistent, aFile);
351 :
352 : // If we don't succeed here, bail early so that we aren't reentrant
353 : // through the "GetProfileDir" call below.
354 0 : return NS_ERROR_FAILURE;
355 : }
356 :
357 41 : if (mAppProvider) {
358 0 : rv = mAppProvider->GetFile(aProperty, aPersistent, aFile);
359 0 : if (NS_SUCCEEDED(rv) && *aFile)
360 0 : return rv;
361 : }
362 :
363 41 : *aPersistent = true;
364 :
365 41 : if (!strcmp(aProperty, NS_GRE_DIR)) {
366 4 : return mGREDir->Clone(aFile);
367 : }
368 37 : else if (!strcmp(aProperty, NS_GRE_BIN_DIR)) {
369 3 : return mGREBinDir->Clone(aFile);
370 : }
371 68 : else if (!strcmp(aProperty, NS_OS_CURRENT_PROCESS_DIR) ||
372 34 : !strcmp(aProperty, NS_APP_INSTALL_CLEANUP_DIR)) {
373 0 : return GetAppDir()->Clone(aFile);
374 : }
375 :
376 34 : rv = NS_ERROR_FAILURE;
377 68 : nsCOMPtr<nsIFile> file;
378 :
379 34 : if (!strcmp(aProperty, NS_APP_PREF_DEFAULTS_50_DIR))
380 : {
381 : // return the GRE default prefs directory here, and the app default prefs
382 : // directory (if applicable) in NS_APP_PREFS_DEFAULTS_DIR_LIST.
383 3 : rv = mGREDir->Clone(getter_AddRefs(file));
384 3 : if (NS_SUCCEEDED(rv)) {
385 3 : rv = file->AppendNative(NS_LITERAL_CSTRING("defaults"));
386 3 : if (NS_SUCCEEDED(rv))
387 3 : rv = file->AppendNative(NS_LITERAL_CSTRING("pref"));
388 : }
389 : }
390 62 : else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_DIR) ||
391 31 : !strcmp(aProperty, XRE_USER_APP_DATA_DIR)) {
392 1 : rv = GetUserAppDataDirectory(getter_AddRefs(file));
393 : }
394 : #if defined(XP_UNIX) || defined(XP_MACOSX)
395 30 : else if (!strcmp(aProperty, XRE_SYS_NATIVE_MESSAGING_MANIFESTS)) {
396 0 : nsCOMPtr<nsIFile> localDir;
397 :
398 0 : rv = ::GetSystemParentDirectory(getter_AddRefs(localDir));
399 0 : if (NS_SUCCEEDED(rv)) {
400 0 : NS_NAMED_LITERAL_CSTRING(dirname,
401 : #if defined(XP_MACOSX)
402 : "NativeMessagingHosts"
403 : #else
404 : "native-messaging-hosts"
405 : #endif
406 : );
407 0 : rv = localDir->AppendNative(dirname);
408 0 : if (NS_SUCCEEDED(rv)) {
409 0 : localDir.swap(file);
410 : }
411 : }
412 : }
413 30 : else if (!strcmp(aProperty, XRE_USER_NATIVE_MESSAGING_MANIFESTS)) {
414 0 : nsCOMPtr<nsIFile> localDir;
415 0 : rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false);
416 0 : if (NS_SUCCEEDED(rv)) {
417 : #if defined(XP_MACOSX)
418 : rv = localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla"));
419 : if (NS_SUCCEEDED(rv)) {
420 : rv = localDir->AppendNative(NS_LITERAL_CSTRING("NativeMessagingHosts"));
421 : }
422 : #else
423 0 : rv = localDir->AppendNative(NS_LITERAL_CSTRING(".mozilla"));
424 0 : if (NS_SUCCEEDED(rv)) {
425 0 : rv = localDir->AppendNative(NS_LITERAL_CSTRING("native-messaging-hosts"));
426 : }
427 : #endif
428 : }
429 0 : if (NS_SUCCEEDED(rv)) {
430 0 : localDir.swap(file);
431 : }
432 : }
433 : #endif
434 30 : else if (!strcmp(aProperty, XRE_UPDATE_ROOT_DIR)) {
435 2 : rv = GetUpdateRootDir(getter_AddRefs(file));
436 : }
437 28 : else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_FILE)) {
438 0 : rv = GetUserAppDataDirectory(getter_AddRefs(file));
439 0 : if (NS_SUCCEEDED(rv))
440 0 : rv = file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME));
441 : }
442 28 : else if (!strcmp(aProperty, NS_APP_USER_PROFILES_ROOT_DIR)) {
443 0 : rv = GetUserProfilesRootDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
444 : }
445 28 : else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) {
446 0 : rv = GetUserProfilesLocalDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
447 : }
448 28 : else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) {
449 6 : nsCOMPtr<nsIFile> lf;
450 3 : rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
451 3 : if (NS_SUCCEEDED(rv))
452 6 : file = lf;
453 : }
454 :
455 25 : else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) {
456 1 : return mProfileDir->Clone(aFile);
457 : }
458 24 : else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
459 1 : if (mProfileLocalDir)
460 1 : return mProfileLocalDir->Clone(aFile);
461 :
462 0 : if (mProfileDir)
463 0 : return mProfileDir->Clone(aFile);
464 :
465 0 : if (mAppProvider)
466 0 : return mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP, aPersistent,
467 0 : aFile);
468 : }
469 : #if defined(XP_UNIX) || defined(XP_MACOSX)
470 23 : else if (!strcmp(aProperty, XRE_SYS_LOCAL_EXTENSION_PARENT_DIR)) {
471 : #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
472 0 : return GetSystemExtensionsDirectory(aFile);
473 : #else
474 : return NS_ERROR_FAILURE;
475 : #endif
476 : }
477 : #endif
478 : #if defined(XP_UNIX) && !defined(XP_MACOSX)
479 23 : else if (!strcmp(aProperty, XRE_SYS_SHARE_EXTENSION_PARENT_DIR)) {
480 : #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
481 : #if defined(__OpenBSD__) || defined(__FreeBSD__)
482 : static const char *const sysLExtDir = "/usr/local/share/mozilla/extensions";
483 : #else
484 : static const char *const sysLExtDir = "/usr/share/mozilla/extensions";
485 : #endif
486 0 : return NS_NewNativeLocalFile(nsDependentCString(sysLExtDir),
487 0 : false, aFile);
488 : #else
489 : return NS_ERROR_FAILURE;
490 : #endif
491 : }
492 : #endif
493 23 : else if (!strcmp(aProperty, XRE_USER_SYS_EXTENSION_DIR)) {
494 : #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
495 0 : return GetSysUserExtensionsDirectory(aFile);
496 : #else
497 : return NS_ERROR_FAILURE;
498 : #endif
499 : }
500 23 : else if (!strcmp(aProperty, XRE_APP_DISTRIBUTION_DIR)) {
501 1 : bool persistent = false;
502 1 : rv = GetFile(NS_GRE_DIR, &persistent, getter_AddRefs(file));
503 1 : if (NS_SUCCEEDED(rv))
504 1 : rv = file->AppendNative(NS_LITERAL_CSTRING("distribution"));
505 : }
506 22 : else if (!strcmp(aProperty, XRE_APP_FEATURES_DIR)) {
507 1 : rv = GetAppDir()->Clone(getter_AddRefs(file));
508 1 : if (NS_SUCCEEDED(rv))
509 1 : rv = file->AppendNative(NS_LITERAL_CSTRING("features"));
510 : }
511 21 : else if (!strcmp(aProperty, XRE_ADDON_APP_DIR)) {
512 2 : nsCOMPtr<nsIDirectoryServiceProvider> dirsvc(do_GetService("@mozilla.org/file/directory_service;1", &rv));
513 1 : if (NS_FAILED(rv))
514 0 : return rv;
515 : bool unused;
516 1 : rv = dirsvc->GetFile("XCurProcD", &unused, getter_AddRefs(file));
517 : }
518 : #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
519 : else if (!strcmp(aProperty, NS_APP_CONTENT_PROCESS_TEMP_DIR)) {
520 : if (!mContentTempDir && NS_FAILED((rv = LoadContentProcessTempDir()))) {
521 : return rv;
522 : }
523 : rv = mContentTempDir->Clone(getter_AddRefs(file));
524 : }
525 : #endif // defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
526 20 : else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file)))) {
527 : // We need to allow component, xpt, and chrome registration to
528 : // occur prior to the profile-after-change notification.
529 15 : if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) {
530 1 : rv = file->AppendNative(NS_LITERAL_CSTRING("chrome"));
531 : }
532 : }
533 :
534 32 : if (NS_SUCCEEDED(rv) && file) {
535 13 : file.forget(aFile);
536 13 : return NS_OK;
537 : }
538 :
539 19 : bool ensureFilePermissions = false;
540 :
541 19 : if (NS_SUCCEEDED(GetProfileDir(getter_AddRefs(file)))) {
542 12 : if (!strcmp(aProperty, NS_APP_PREFS_50_DIR)) {
543 1 : rv = NS_OK;
544 : }
545 11 : else if (!strcmp(aProperty, NS_APP_PREFS_50_FILE)) {
546 1 : rv = file->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
547 : }
548 10 : else if (!strcmp(aProperty, NS_LOCALSTORE_UNSAFE_FILE)) {
549 0 : rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
550 : }
551 10 : else if (!strcmp(aProperty, NS_APP_LOCALSTORE_50_FILE)) {
552 0 : if (gSafeMode) {
553 0 : rv = file->AppendNative(NS_LITERAL_CSTRING("localstore-safe.rdf"));
554 0 : file->Remove(false);
555 : }
556 : else {
557 0 : rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
558 0 : ensureFilePermissions = true;
559 : }
560 : }
561 10 : else if (!strcmp(aProperty, NS_APP_PREFS_OVERRIDE_DIR)) {
562 0 : rv = mProfileDir->Clone(getter_AddRefs(file));
563 0 : nsresult tmp = file->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
564 0 : if (NS_FAILED(tmp)) {
565 0 : rv = tmp;
566 : }
567 0 : tmp = EnsureDirectoryExists(file);
568 0 : if (NS_FAILED(tmp)) {
569 0 : rv = tmp;
570 : }
571 : }
572 : }
573 19 : if (NS_FAILED(rv) || !file)
574 17 : return NS_ERROR_FAILURE;
575 :
576 2 : if (ensureFilePermissions) {
577 : bool fileToEnsureExists;
578 : bool isWritable;
579 0 : if (NS_SUCCEEDED(file->Exists(&fileToEnsureExists)) && fileToEnsureExists
580 0 : && NS_SUCCEEDED(file->IsWritable(&isWritable)) && !isWritable) {
581 : uint32_t permissions;
582 0 : if (NS_SUCCEEDED(file->GetPermissions(&permissions))) {
583 0 : rv = file->SetPermissions(permissions | 0600);
584 0 : NS_ASSERTION(NS_SUCCEEDED(rv), "failed to ensure file permissions");
585 : }
586 : }
587 : }
588 :
589 2 : file.forget(aFile);
590 2 : return NS_OK;
591 : }
592 :
593 : static void
594 40 : LoadDirIntoArray(nsIFile* dir,
595 : const char *const *aAppendList,
596 : nsCOMArray<nsIFile>& aDirectories)
597 : {
598 40 : if (!dir)
599 0 : return;
600 :
601 80 : nsCOMPtr<nsIFile> subdir;
602 40 : dir->Clone(getter_AddRefs(subdir));
603 40 : if (!subdir)
604 0 : return;
605 :
606 83 : for (const char *const *a = aAppendList; *a; ++a) {
607 43 : subdir->AppendNative(nsDependentCString(*a));
608 : }
609 :
610 : bool exists;
611 40 : if (NS_SUCCEEDED(subdir->Exists(&exists)) && exists) {
612 35 : aDirectories.AppendObject(subdir);
613 : }
614 : }
615 :
616 : static void
617 32 : LoadDirsIntoArray(const nsCOMArray<nsIFile>& aSourceDirs,
618 : const char *const* aAppendList,
619 : nsCOMArray<nsIFile>& aDirectories)
620 : {
621 64 : nsCOMPtr<nsIFile> appended;
622 : bool exists;
623 :
624 59 : for (int32_t i = 0; i < aSourceDirs.Count(); ++i) {
625 27 : aSourceDirs[i]->Clone(getter_AddRefs(appended));
626 27 : if (!appended)
627 0 : continue;
628 :
629 54 : nsAutoCString leaf;
630 27 : appended->GetNativeLeafName(leaf);
631 27 : if (!Substring(leaf, leaf.Length() - 4).EqualsLiteral(".xpi")) {
632 27 : LoadDirIntoArray(appended,
633 : aAppendList,
634 27 : aDirectories);
635 : }
636 0 : else if (NS_SUCCEEDED(appended->Exists(&exists)) && exists)
637 0 : aDirectories.AppendObject(appended);
638 : }
639 32 : }
640 :
641 : NS_IMETHODIMP
642 20 : nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult)
643 : {
644 : nsresult rv;
645 :
646 40 : nsCOMPtr<nsISimpleEnumerator> appEnum;
647 : nsCOMPtr<nsIDirectoryServiceProvider2>
648 40 : appP2(do_QueryInterface(mAppProvider));
649 20 : if (appP2) {
650 0 : rv = appP2->GetFiles(aProperty, getter_AddRefs(appEnum));
651 0 : if (NS_FAILED(rv)) {
652 0 : appEnum = nullptr;
653 : }
654 0 : else if (rv != NS_SUCCESS_AGGREGATE_RESULT) {
655 0 : appEnum.forget(aResult);
656 0 : return NS_OK;
657 : }
658 : }
659 :
660 40 : nsCOMPtr<nsISimpleEnumerator> xreEnum;
661 20 : rv = GetFilesInternal(aProperty, getter_AddRefs(xreEnum));
662 20 : if (NS_FAILED(rv)) {
663 1 : if (appEnum) {
664 0 : appEnum.forget(aResult);
665 0 : return NS_SUCCESS_AGGREGATE_RESULT;
666 : }
667 :
668 1 : return rv;
669 : }
670 :
671 19 : rv = NS_NewUnionEnumerator(aResult, appEnum, xreEnum);
672 19 : if (NS_FAILED(rv))
673 0 : return rv;
674 :
675 19 : return NS_SUCCESS_AGGREGATE_RESULT;
676 : }
677 :
678 : #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
679 :
680 : static const char*
681 : GetContentProcessTempBaseDirKey()
682 : {
683 : #if defined(XP_WIN)
684 : return NS_WIN_LOW_INTEGRITY_TEMP_BASE;
685 : #else
686 : return NS_OS_TEMP_DIR;
687 : #endif
688 : }
689 :
690 : //
691 : // Sets mContentTempDir so that it refers to the appropriate temp dir.
692 : // If the sandbox is enabled, NS_APP_CONTENT_PROCESS_TEMP_DIR, otherwise
693 : // NS_OS_TEMP_DIR is used.
694 : //
695 : nsresult
696 : nsXREDirProvider::LoadContentProcessTempDir()
697 : {
698 : // The parent is responsible for creating the sandbox temp dir.
699 : if (XRE_IsParentProcess()) {
700 : mContentProcessSandboxTempDir = CreateContentProcessSandboxTempDir();
701 : mContentTempDir = mContentProcessSandboxTempDir;
702 : } else {
703 : mContentTempDir = GetContentProcessSandboxTempDir();
704 : }
705 :
706 : if (!mContentTempDir) {
707 : nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR,
708 : getter_AddRefs(mContentTempDir));
709 : if (NS_WARN_IF(NS_FAILED(rv))) {
710 : return rv;
711 : }
712 : }
713 :
714 : #if defined(XP_WIN)
715 : // The content temp dir can be used in sandbox rules, so we need to make sure
716 : // it doesn't contain any junction points or symlinks or the sandbox will
717 : // reject those rules.
718 : if (!mozilla::widget::WinUtils::ResolveJunctionPointsAndSymLinks(mContentTempDir)) {
719 : NS_WARNING("Failed to resolve Content Temp Dir.");
720 : }
721 : #endif
722 :
723 : return NS_OK;
724 : }
725 :
726 : static bool
727 : IsContentSandboxDisabled()
728 : {
729 : return !BrowserTabsRemoteAutostart() || (GetEffectiveContentSandboxLevel() < 1);
730 : }
731 :
732 : //
733 : // If a content process sandbox temp dir is to be used, returns an nsIFile
734 : // for the directory. Returns null if the content sandbox is disabled or
735 : // an error occurs.
736 : //
737 : static already_AddRefed<nsIFile>
738 : GetContentProcessSandboxTempDir()
739 : {
740 : if (IsContentSandboxDisabled()) {
741 : return nullptr;
742 : }
743 :
744 : nsCOMPtr<nsIFile> localFile;
745 :
746 : nsresult rv = NS_GetSpecialDirectory(GetContentProcessTempBaseDirKey(),
747 : getter_AddRefs(localFile));
748 : if (NS_WARN_IF(NS_FAILED(rv))) {
749 : return nullptr;
750 : }
751 :
752 : nsAutoString tempDirSuffix;
753 : rv = Preferences::GetString("security.sandbox.content.tempDirSuffix",
754 : &tempDirSuffix);
755 : if (NS_WARN_IF(NS_FAILED(rv)) || tempDirSuffix.IsEmpty()) {
756 : return nullptr;
757 : }
758 :
759 : rv = localFile->Append(NS_LITERAL_STRING("Temp-") + tempDirSuffix);
760 : if (NS_WARN_IF(NS_FAILED(rv))) {
761 : return nullptr;
762 : }
763 :
764 : return localFile.forget();
765 : }
766 :
767 : //
768 : // Create a temporary directory for use from sandboxed content processes.
769 : // Only called in the parent. The path is derived from a UUID stored in a
770 : // pref which is available to content processes. Returns null if the
771 : // content sandbox is disabled or if an error occurs.
772 : //
773 : static already_AddRefed<nsIFile>
774 : CreateContentProcessSandboxTempDir()
775 : {
776 : if (IsContentSandboxDisabled()) {
777 : return nullptr;
778 : }
779 :
780 : // Get (and create if blank) temp directory suffix pref.
781 : nsresult rv;
782 : nsAdoptingString tempDirSuffix =
783 : Preferences::GetString("security.sandbox.content.tempDirSuffix");
784 : if (tempDirSuffix.IsEmpty()) {
785 : nsCOMPtr<nsIUUIDGenerator> uuidgen =
786 : do_GetService("@mozilla.org/uuid-generator;1", &rv);
787 : if (NS_WARN_IF(NS_FAILED(rv))) {
788 : return nullptr;
789 : }
790 :
791 : nsID uuid;
792 : rv = uuidgen->GenerateUUIDInPlace(&uuid);
793 : if (NS_WARN_IF(NS_FAILED(rv))) {
794 : return nullptr;
795 : }
796 :
797 : char uuidChars[NSID_LENGTH];
798 : uuid.ToProvidedString(uuidChars);
799 : tempDirSuffix.AssignASCII(uuidChars);
800 :
801 : // Save the pref
802 : rv = Preferences::SetCString("security.sandbox.content.tempDirSuffix",
803 : uuidChars);
804 : if (NS_WARN_IF(NS_FAILED(rv))) {
805 : // If we fail to save the pref we don't want to create the temp dir,
806 : // because we won't be able to clean it up later.
807 : return nullptr;
808 : }
809 :
810 : nsCOMPtr<nsIPrefService> prefsvc = Preferences::GetService();
811 : if (!prefsvc || NS_FAILED((rv = prefsvc->SavePrefFile(nullptr)))) {
812 : // Again, if we fail to save the pref file we might not be able to clean
813 : // up the temp directory, so don't create one. Note that in the case
814 : // the preference values allows an off main thread save, the successful
815 : // return from the call doesn't mean we actually saved the file. See
816 : // bug 1364496 for details.
817 : NS_WARNING("Failed to save pref file, cannot create temp dir.");
818 : return nullptr;
819 : }
820 : }
821 :
822 : nsCOMPtr<nsIFile> sandboxTempDir = GetContentProcessSandboxTempDir();
823 : if (!sandboxTempDir) {
824 : NS_WARNING("Failed to determine sandbox temp dir path.");
825 : return nullptr;
826 : }
827 :
828 : // Remove the directory. It may exist due to a previous crash.
829 : if (NS_FAILED(DeleteDirIfExists(sandboxTempDir))) {
830 : NS_WARNING("Failed to reset sandbox temp dir.");
831 : return nullptr;
832 : }
833 :
834 : // Create the directory
835 : rv = sandboxTempDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
836 : if (NS_FAILED(rv)) {
837 : NS_WARNING("Failed to create sandbox temp dir.");
838 : return nullptr;
839 : }
840 :
841 : return sandboxTempDir.forget();
842 : }
843 :
844 : static nsresult
845 : DeleteDirIfExists(nsIFile* dir)
846 : {
847 : if (dir) {
848 : // Don't return an error if the directory doesn't exist.
849 : // Windows Remove() returns NS_ERROR_FILE_NOT_FOUND while
850 : // OS X returns NS_ERROR_FILE_TARGET_DOES_NOT_EXIST.
851 : nsresult rv = dir->Remove(/* aRecursive */ true);
852 : if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND &&
853 : rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
854 : return rv;
855 : }
856 : }
857 : return NS_OK;
858 : }
859 :
860 : #endif // (defined(XP_WIN) || defined(XP_MACOSX)) &&
861 : // defined(MOZ_CONTENT_SANDBOX)
862 :
863 : #ifdef MOZ_B2G
864 : void
865 : nsXREDirProvider::LoadAppBundleDirs()
866 : {
867 : nsCOMPtr<nsIFile> dir;
868 : bool persistent = false;
869 : nsresult rv = GetFile(XRE_APP_DISTRIBUTION_DIR, &persistent, getter_AddRefs(dir));
870 : if (NS_FAILED(rv))
871 : return;
872 :
873 : dir->AppendNative(NS_LITERAL_CSTRING("bundles"));
874 :
875 : nsCOMPtr<nsISimpleEnumerator> e;
876 : rv = dir->GetDirectoryEntries(getter_AddRefs(e));
877 : if (NS_FAILED(rv))
878 : return;
879 :
880 : nsCOMPtr<nsIDirectoryEnumerator> files = do_QueryInterface(e);
881 : if (!files)
882 : return;
883 :
884 : nsCOMPtr<nsIFile> subdir;
885 : while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(subdir))) && subdir) {
886 : mAppBundleDirectories.AppendObject(subdir);
887 :
888 : nsCOMPtr<nsIFile> manifest =
889 : CloneAndAppend(subdir, "chrome.manifest");
890 : XRE_AddManifestLocation(NS_APP_LOCATION, manifest);
891 : }
892 : }
893 : #endif
894 :
895 : static const char *const kAppendPrefDir[] = { "defaults", "preferences", nullptr };
896 :
897 : #ifdef DEBUG_bsmedberg
898 : static void
899 : DumpFileArray(const char *key,
900 : nsCOMArray<nsIFile> dirs)
901 : {
902 : fprintf(stderr, "nsXREDirProvider::GetFilesInternal(%s)\n", key);
903 :
904 : nsAutoCString path;
905 : for (int32_t i = 0; i < dirs.Count(); ++i) {
906 : dirs[i]->GetNativePath(path);
907 : fprintf(stderr, " %s\n", path.get());
908 : }
909 : }
910 : #endif // DEBUG_bsmedberg
911 :
912 : nsresult
913 20 : nsXREDirProvider::GetFilesInternal(const char* aProperty,
914 : nsISimpleEnumerator** aResult)
915 : {
916 20 : nsresult rv = NS_OK;
917 20 : *aResult = nullptr;
918 :
919 20 : if (!strcmp(aProperty, XRE_EXTENSIONS_DIR_LIST)) {
920 2 : nsCOMArray<nsIFile> directories;
921 :
922 : static const char *const kAppendNothing[] = { nullptr };
923 :
924 1 : LoadDirsIntoArray(mAppBundleDirectories,
925 1 : kAppendNothing, directories);
926 1 : LoadDirsIntoArray(AddonManagerStartup::GetSingleton().ExtensionPaths(),
927 1 : kAppendNothing, directories);
928 :
929 1 : rv = NS_NewArrayEnumerator(aResult, directories);
930 : }
931 19 : else if (!strcmp(aProperty, NS_APP_PREFS_DEFAULTS_DIR_LIST)) {
932 6 : nsCOMArray<nsIFile> directories;
933 :
934 3 : LoadDirIntoArray(mXULAppDir, kAppendPrefDir, directories);
935 3 : LoadDirsIntoArray(mAppBundleDirectories,
936 3 : kAppendPrefDir, directories);
937 :
938 3 : rv = NS_NewArrayEnumerator(aResult, directories);
939 : }
940 16 : else if (!strcmp(aProperty, NS_EXT_PREFS_DEFAULTS_DIR_LIST)) {
941 8 : nsCOMArray<nsIFile> directories;
942 :
943 4 : LoadDirsIntoArray(AddonManagerStartup::GetSingleton().ExtensionPaths(),
944 4 : kAppendPrefDir, directories);
945 :
946 4 : if (mProfileDir) {
947 4 : nsCOMPtr<nsIFile> overrideFile;
948 2 : mProfileDir->Clone(getter_AddRefs(overrideFile));
949 2 : overrideFile->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
950 :
951 : bool exists;
952 2 : if (NS_SUCCEEDED(overrideFile->Exists(&exists)) && exists)
953 0 : directories.AppendObject(overrideFile);
954 : }
955 :
956 4 : rv = NS_NewArrayEnumerator(aResult, directories);
957 : }
958 12 : else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) {
959 : // NS_APP_CHROME_DIR_LIST is only used to get default (native) icons
960 : // for OS window decoration.
961 :
962 : static const char *const kAppendChromeDir[] = { "chrome", nullptr };
963 20 : nsCOMArray<nsIFile> directories;
964 10 : LoadDirIntoArray(mXULAppDir,
965 : kAppendChromeDir,
966 10 : directories);
967 10 : LoadDirsIntoArray(mAppBundleDirectories,
968 : kAppendChromeDir,
969 10 : directories);
970 10 : LoadDirsIntoArray(AddonManagerStartup::GetSingleton().ExtensionPaths(),
971 : kAppendChromeDir,
972 10 : directories);
973 :
974 10 : rv = NS_NewArrayEnumerator(aResult, directories);
975 : }
976 2 : else if (!strcmp(aProperty, NS_APP_PLUGINS_DIR_LIST)) {
977 2 : nsCOMArray<nsIFile> directories;
978 :
979 1 : if (mozilla::Preferences::GetBool("plugins.load_appdir_plugins", false)) {
980 0 : nsCOMPtr<nsIFile> appdir;
981 0 : rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(appdir));
982 0 : if (NS_SUCCEEDED(rv)) {
983 0 : appdir->SetNativeLeafName(NS_LITERAL_CSTRING("plugins"));
984 0 : directories.AppendObject(appdir);
985 : }
986 : }
987 :
988 : static const char *const kAppendPlugins[] = { "plugins", nullptr };
989 :
990 : // The root dirserviceprovider does quite a bit for us: we're mainly
991 : // interested in xulapp and extension-provided plugins.
992 1 : LoadDirsIntoArray(mAppBundleDirectories,
993 : kAppendPlugins,
994 1 : directories);
995 1 : LoadDirsIntoArray(AddonManagerStartup::GetSingleton().ExtensionPaths(),
996 : kAppendPlugins,
997 1 : directories);
998 :
999 1 : if (mProfileDir) {
1000 2 : nsCOMArray<nsIFile> profileDir;
1001 1 : profileDir.AppendObject(mProfileDir);
1002 : LoadDirsIntoArray(profileDir,
1003 : kAppendPlugins,
1004 1 : directories);
1005 : }
1006 :
1007 1 : rv = NS_NewArrayEnumerator(aResult, directories);
1008 1 : NS_ENSURE_SUCCESS(rv, rv);
1009 :
1010 1 : rv = NS_SUCCESS_AGGREGATE_RESULT;
1011 : }
1012 : else
1013 1 : rv = NS_ERROR_FAILURE;
1014 :
1015 20 : return rv;
1016 : }
1017 :
1018 : NS_IMETHODIMP
1019 0 : nsXREDirProvider::GetDirectory(nsIFile* *aResult)
1020 : {
1021 0 : NS_ENSURE_TRUE(mProfileDir, NS_ERROR_NOT_INITIALIZED);
1022 :
1023 0 : return mProfileDir->Clone(aResult);
1024 : }
1025 :
1026 : NS_IMETHODIMP
1027 1 : nsXREDirProvider::DoStartup()
1028 : {
1029 1 : if (!mProfileNotified) {
1030 : nsCOMPtr<nsIObserverService> obsSvc =
1031 2 : mozilla::services::GetObserverService();
1032 1 : if (!obsSvc) return NS_ERROR_FAILURE;
1033 :
1034 1 : mProfileNotified = true;
1035 :
1036 : /*
1037 : Setup prefs before profile-do-change to be able to use them to track
1038 : crashes and because we want to begin crash tracking before other code run
1039 : from this notification since they may cause crashes.
1040 : */
1041 1 : nsresult rv = mozilla::Preferences::ResetAndReadUserPrefs();
1042 1 : if (NS_FAILED(rv)) NS_WARNING("Failed to setup pref service.");
1043 :
1044 1 : bool safeModeNecessary = false;
1045 2 : nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
1046 1 : if (appStartup) {
1047 1 : rv = appStartup->TrackStartupCrashBegin(&safeModeNecessary);
1048 1 : if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE)
1049 0 : NS_WARNING("Error while beginning startup crash tracking");
1050 :
1051 1 : if (!gSafeMode && safeModeNecessary) {
1052 0 : appStartup->RestartInSafeMode(nsIAppStartup::eForceQuit);
1053 0 : return NS_OK;
1054 : }
1055 : }
1056 :
1057 : static const char16_t kStartup[] = {'s','t','a','r','t','u','p','\0'};
1058 1 : obsSvc->NotifyObservers(nullptr, "profile-do-change", kStartup);
1059 :
1060 : // Init the Extension Manager
1061 2 : nsCOMPtr<nsIObserver> em = do_GetService("@mozilla.org/addons/integration;1");
1062 1 : if (em) {
1063 1 : em->Observe(nullptr, "addons-startup", nullptr);
1064 : } else {
1065 0 : NS_WARNING("Failed to create Addons Manager.");
1066 : }
1067 :
1068 1 : obsSvc->NotifyObservers(nullptr, "load-extension-defaults", nullptr);
1069 1 : obsSvc->NotifyObservers(nullptr, "profile-after-change", kStartup);
1070 :
1071 : // Any component that has registered for the profile-after-change category
1072 : // should also be created at this time.
1073 : (void)NS_CreateServicesFromCategory("profile-after-change", nullptr,
1074 1 : "profile-after-change");
1075 :
1076 1 : if (gSafeMode && safeModeNecessary) {
1077 : static const char16_t kCrashed[] = {'c','r','a','s','h','e','d','\0'};
1078 0 : obsSvc->NotifyObservers(nullptr, "safemode-forced", kCrashed);
1079 : }
1080 :
1081 : // 1 = Regular mode, 2 = Safe mode, 3 = Safe mode forced
1082 1 : int mode = 1;
1083 1 : if (gSafeMode) {
1084 0 : if (safeModeNecessary)
1085 0 : mode = 3;
1086 : else
1087 0 : mode = 2;
1088 : }
1089 1 : mozilla::Telemetry::Accumulate(mozilla::Telemetry::SAFE_MODE_USAGE, mode);
1090 :
1091 : // Telemetry about number of profiles.
1092 : nsCOMPtr<nsIToolkitProfileService> profileService =
1093 2 : do_GetService("@mozilla.org/toolkit/profile-service;1");
1094 1 : if (profileService) {
1095 2 : nsCOMPtr<nsISimpleEnumerator> profiles;
1096 1 : rv = profileService->GetProfiles(getter_AddRefs(profiles));
1097 1 : if (NS_WARN_IF(NS_FAILED(rv))) {
1098 0 : return rv;
1099 : }
1100 :
1101 1 : uint32_t count = 0;
1102 2 : nsCOMPtr<nsISupports> profile;
1103 3 : while (NS_SUCCEEDED(profiles->GetNext(getter_AddRefs(profile)))) {
1104 1 : ++count;
1105 : }
1106 :
1107 : mozilla::Telemetry::Accumulate(mozilla::Telemetry::NUMBER_OF_PROFILES,
1108 1 : count);
1109 : }
1110 :
1111 1 : obsSvc->NotifyObservers(nullptr, "profile-initial-state", nullptr);
1112 :
1113 : #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
1114 : // Makes sure the content temp dir has been loaded if it hasn't been
1115 : // already. In the parent this ensures it has been created before we attempt
1116 : // to start any content processes.
1117 : if (!mContentTempDir) {
1118 : mozilla::Unused << NS_WARN_IF(NS_FAILED(LoadContentProcessTempDir()));
1119 : }
1120 : #endif
1121 : }
1122 1 : return NS_OK;
1123 : }
1124 :
1125 : void
1126 0 : nsXREDirProvider::DoShutdown()
1127 : {
1128 0 : AUTO_PROFILER_LABEL("nsXREDirProvider::DoShutdown", OTHER);
1129 :
1130 0 : if (mProfileNotified) {
1131 : nsCOMPtr<nsIObserverService> obsSvc =
1132 0 : mozilla::services::GetObserverService();
1133 0 : NS_ASSERTION(obsSvc, "No observer service?");
1134 0 : if (obsSvc) {
1135 : static const char16_t kShutdownPersist[] = u"shutdown-persist";
1136 0 : obsSvc->NotifyObservers(nullptr, "profile-change-net-teardown", kShutdownPersist);
1137 0 : obsSvc->NotifyObservers(nullptr, "profile-change-teardown", kShutdownPersist);
1138 0 : obsSvc->NotifyObservers(nullptr, "profile-before-change", kShutdownPersist);
1139 0 : obsSvc->NotifyObservers(nullptr, "profile-before-change-qm", kShutdownPersist);
1140 0 : obsSvc->NotifyObservers(nullptr, "profile-before-change-telemetry", kShutdownPersist);
1141 : }
1142 0 : mProfileNotified = false;
1143 : }
1144 :
1145 : #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
1146 : if (XRE_IsParentProcess()) {
1147 : Unused << DeleteDirIfExists(mContentProcessSandboxTempDir);
1148 : }
1149 : #endif
1150 0 : }
1151 :
1152 : #ifdef XP_WIN
1153 : static nsresult
1154 : GetShellFolderPath(KNOWNFOLDERID folder, nsAString& _retval)
1155 : {
1156 : DWORD flags = KF_FLAG_SIMPLE_IDLIST | KF_FLAG_DONT_VERIFY | KF_FLAG_NO_ALIAS;
1157 : PWSTR path = nullptr;
1158 :
1159 : if (!SUCCEEDED(SHGetKnownFolderPath(folder, flags, NULL, &path))) {
1160 : return NS_ERROR_NOT_AVAILABLE;
1161 : }
1162 :
1163 : _retval = nsDependentString(path);
1164 : CoTaskMemFree(path);
1165 : return NS_OK;
1166 : }
1167 :
1168 : /**
1169 : * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
1170 : * querying the registry when the call to SHGetSpecialFolderLocation or
1171 : * SHGetPathFromIDListW is unable to provide these paths (Bug 513958).
1172 : */
1173 : static nsresult
1174 : GetRegWindowsAppDataFolder(bool aLocal, nsAString& _retval)
1175 : {
1176 : HKEY key;
1177 : LPCWSTR keyName =
1178 : L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
1179 : DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName, 0, KEY_READ,
1180 : &key);
1181 : if (res != ERROR_SUCCESS) {
1182 : _retval.SetLength(0);
1183 : return NS_ERROR_NOT_AVAILABLE;
1184 : }
1185 :
1186 : DWORD type, size;
1187 : res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
1188 : nullptr, &type, nullptr, &size);
1189 : // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the
1190 : // buffer size must not equal 0, and the buffer size be a multiple of 2.
1191 : if (res != ERROR_SUCCESS || type != REG_SZ || size == 0 || size % 2 != 0) {
1192 : ::RegCloseKey(key);
1193 : _retval.SetLength(0);
1194 : return NS_ERROR_NOT_AVAILABLE;
1195 : }
1196 :
1197 : // |size| may or may not include room for the terminating null character
1198 : DWORD resultLen = size / 2;
1199 :
1200 : if (!_retval.SetLength(resultLen, mozilla::fallible)) {
1201 : ::RegCloseKey(key);
1202 : _retval.SetLength(0);
1203 : return NS_ERROR_NOT_AVAILABLE;
1204 : }
1205 :
1206 : nsAString::iterator begin;
1207 : _retval.BeginWriting(begin);
1208 :
1209 : res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
1210 : nullptr, nullptr, (LPBYTE) begin.get(), &size);
1211 : ::RegCloseKey(key);
1212 : if (res != ERROR_SUCCESS) {
1213 : _retval.SetLength(0);
1214 : return NS_ERROR_NOT_AVAILABLE;
1215 : }
1216 :
1217 : if (!_retval.CharAt(resultLen - 1)) {
1218 : // It was already null terminated.
1219 : _retval.Truncate(resultLen - 1);
1220 : }
1221 :
1222 : return NS_OK;
1223 : }
1224 :
1225 : static bool
1226 : GetCachedHash(HKEY rootKey, const nsAString ®Path, const nsAString &path,
1227 : nsAString &cachedHash)
1228 : {
1229 : HKEY baseKey;
1230 : if (RegOpenKeyExW(rootKey, reinterpret_cast<const wchar_t*>(regPath.BeginReading()), 0, KEY_READ, &baseKey) !=
1231 : ERROR_SUCCESS) {
1232 : return false;
1233 : }
1234 :
1235 : wchar_t cachedHashRaw[512];
1236 : DWORD bufferSize = sizeof(cachedHashRaw);
1237 : LONG result = RegQueryValueExW(baseKey, reinterpret_cast<const wchar_t*>(path.BeginReading()), 0, nullptr,
1238 : (LPBYTE)cachedHashRaw, &bufferSize);
1239 : RegCloseKey(baseKey);
1240 : if (result == ERROR_SUCCESS) {
1241 : cachedHash.Assign(cachedHashRaw);
1242 : }
1243 : return ERROR_SUCCESS == result;
1244 : }
1245 :
1246 : #endif
1247 :
1248 : nsresult
1249 2 : nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult)
1250 : {
1251 4 : nsCOMPtr<nsIFile> updRoot;
1252 : #if defined(MOZ_WIDGET_GONK)
1253 :
1254 : nsresult rv = NS_NewNativeLocalFile(nsDependentCString("/data/local"),
1255 : true,
1256 : getter_AddRefs(updRoot));
1257 : NS_ENSURE_SUCCESS(rv, rv);
1258 :
1259 : #else
1260 4 : nsCOMPtr<nsIFile> appFile;
1261 2 : bool per = false;
1262 2 : nsresult rv = GetFile(XRE_EXECUTABLE_FILE, &per, getter_AddRefs(appFile));
1263 2 : NS_ENSURE_SUCCESS(rv, rv);
1264 2 : rv = appFile->GetParent(getter_AddRefs(updRoot));
1265 2 : NS_ENSURE_SUCCESS(rv, rv);
1266 :
1267 : #ifdef XP_MACOSX
1268 : nsCOMPtr<nsIFile> appRootDirFile;
1269 : nsCOMPtr<nsIFile> localDir;
1270 : nsAutoString appDirPath;
1271 : if (NS_FAILED(appFile->GetParent(getter_AddRefs(appRootDirFile))) ||
1272 : NS_FAILED(appRootDirFile->GetPath(appDirPath)) ||
1273 : NS_FAILED(GetUserDataDirectoryHome(getter_AddRefs(localDir), true))) {
1274 : return NS_ERROR_FAILURE;
1275 : }
1276 :
1277 : int32_t dotIndex = appDirPath.RFind(".app");
1278 : if (dotIndex == kNotFound) {
1279 : dotIndex = appDirPath.Length();
1280 : }
1281 : appDirPath = Substring(appDirPath, 1, dotIndex - 1);
1282 :
1283 : bool hasVendor = gAppData->vendor && strlen(gAppData->vendor) != 0;
1284 : if (hasVendor || gAppData->name) {
1285 : if (NS_FAILED(localDir->AppendNative(nsDependentCString(hasVendor ?
1286 : gAppData->vendor :
1287 : gAppData->name)))) {
1288 : return NS_ERROR_FAILURE;
1289 : }
1290 : } else if (NS_FAILED(localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla")))) {
1291 : return NS_ERROR_FAILURE;
1292 : }
1293 :
1294 : if (NS_FAILED(localDir->Append(NS_LITERAL_STRING("updates"))) ||
1295 : NS_FAILED(localDir->AppendRelativePath(appDirPath))) {
1296 : return NS_ERROR_FAILURE;
1297 : }
1298 :
1299 : localDir.forget(aResult);
1300 : return NS_OK;
1301 :
1302 : #elif XP_WIN
1303 : nsAutoString pathHash;
1304 : bool pathHashResult = false;
1305 : bool hasVendor = gAppData->vendor && strlen(gAppData->vendor) != 0;
1306 :
1307 : nsAutoString appDirPath;
1308 : if (SUCCEEDED(updRoot->GetPath(appDirPath))) {
1309 :
1310 : // Figure out where we should check for a cached hash value. If the
1311 : // application doesn't have the nsXREAppData vendor value defined check
1312 : // under SOFTWARE\Mozilla.
1313 : wchar_t regPath[1024] = { L'\0' };
1314 : swprintf_s(regPath, mozilla::ArrayLength(regPath), L"SOFTWARE\\%S\\%S\\TaskBarIDs",
1315 : (hasVendor ? gAppData->vendor : "Mozilla"), MOZ_APP_BASENAME);
1316 :
1317 : // If we pre-computed the hash, grab it from the registry.
1318 : pathHashResult = GetCachedHash(HKEY_LOCAL_MACHINE,
1319 : nsDependentString(regPath), appDirPath,
1320 : pathHash);
1321 : if (!pathHashResult) {
1322 : pathHashResult = GetCachedHash(HKEY_CURRENT_USER,
1323 : nsDependentString(regPath), appDirPath,
1324 : pathHash);
1325 : }
1326 : }
1327 :
1328 : if (!pathHashResult) {
1329 : // This should only happen when the installer isn't used (e.g. zip builds).
1330 : uint64_t hash = CityHash64(static_cast<const char *>(appDirPath.get()),
1331 : appDirPath.Length() * sizeof(nsAutoString::char_type));
1332 : pathHash.AppendInt((int)(hash >> 32), 16);
1333 : pathHash.AppendInt((int)hash, 16);
1334 : // The installer implementation writes the registry values that were checked
1335 : // in the previous block for this value in uppercase and since it is an
1336 : // option to have a case sensitive file system on Windows this value must
1337 : // also be in uppercase.
1338 : ToUpperCase(pathHash);
1339 : }
1340 :
1341 : // As a last ditch effort, get the local app data directory and if a vendor
1342 : // name exists append it. If only a product name exists, append it. If neither
1343 : // exist fallback to old handling. We don't use the product name on purpose
1344 : // because we want a shared update directory for different apps run from the
1345 : // same path.
1346 : nsCOMPtr<nsIFile> localDir;
1347 : if ((hasVendor || gAppData->name) &&
1348 : NS_SUCCEEDED(GetUserDataDirectoryHome(getter_AddRefs(localDir), true)) &&
1349 : NS_SUCCEEDED(localDir->AppendNative(nsDependentCString(hasVendor ?
1350 : gAppData->vendor : gAppData->name))) &&
1351 : NS_SUCCEEDED(localDir->Append(NS_LITERAL_STRING("updates"))) &&
1352 : NS_SUCCEEDED(localDir->Append(pathHash))) {
1353 : localDir.forget(aResult);
1354 : return NS_OK;
1355 : }
1356 :
1357 : nsAutoString appPath;
1358 : rv = updRoot->GetPath(appPath);
1359 : NS_ENSURE_SUCCESS(rv, rv);
1360 :
1361 : // AppDir may be a short path. Convert to long path to make sure
1362 : // the consistency of the update folder location
1363 : nsString longPath;
1364 : wchar_t* buf;
1365 :
1366 : uint32_t bufLength = longPath.GetMutableData(&buf, MAXPATHLEN);
1367 : NS_ENSURE_TRUE(bufLength >= MAXPATHLEN, NS_ERROR_OUT_OF_MEMORY);
1368 :
1369 : DWORD len = GetLongPathNameW(appPath.get(), buf, bufLength);
1370 :
1371 : // Failing GetLongPathName() is not fatal.
1372 : if (len <= 0 || len >= bufLength)
1373 : longPath.Assign(appPath);
1374 : else
1375 : longPath.SetLength(len);
1376 :
1377 : // Use <UserLocalDataDir>\updates\<relative path to app dir from
1378 : // Program Files> if app dir is under Program Files to avoid the
1379 : // folder virtualization mess on Windows Vista
1380 : nsAutoString programFiles;
1381 : rv = GetShellFolderPath(FOLDERID_ProgramFiles, programFiles);
1382 : NS_ENSURE_SUCCESS(rv, rv);
1383 :
1384 : programFiles.Append('\\');
1385 : uint32_t programFilesLen = programFiles.Length();
1386 :
1387 : nsAutoString programName;
1388 : if (_wcsnicmp(programFiles.get(), longPath.get(), programFilesLen) == 0) {
1389 : programName = Substring(longPath, programFilesLen);
1390 : } else {
1391 : // We need the update root directory to live outside of the installation
1392 : // directory, because otherwise the updater writing the log file can cause
1393 : // the directory to be locked, which prevents it from being replaced after
1394 : // background updates.
1395 : programName.AssignASCII(MOZ_APP_NAME);
1396 : }
1397 :
1398 : rv = GetUserLocalDataDirectory(getter_AddRefs(updRoot));
1399 : NS_ENSURE_SUCCESS(rv, rv);
1400 :
1401 : rv = updRoot->AppendRelativePath(programName);
1402 : NS_ENSURE_SUCCESS(rv, rv);
1403 :
1404 : #endif // XP_WIN
1405 : #endif
1406 2 : updRoot.forget(aResult);
1407 2 : return NS_OK;
1408 : }
1409 :
1410 : nsresult
1411 20 : nsXREDirProvider::GetProfileStartupDir(nsIFile* *aResult)
1412 : {
1413 20 : if (mProfileDir)
1414 15 : return mProfileDir->Clone(aResult);
1415 :
1416 5 : if (mAppProvider) {
1417 0 : nsCOMPtr<nsIFile> needsclone;
1418 : bool dummy;
1419 0 : nsresult rv = mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP,
1420 : &dummy,
1421 0 : getter_AddRefs(needsclone));
1422 0 : if (NS_SUCCEEDED(rv))
1423 0 : return needsclone->Clone(aResult);
1424 : }
1425 :
1426 5 : return NS_ERROR_FAILURE;
1427 : }
1428 :
1429 : nsresult
1430 19 : nsXREDirProvider::GetProfileDir(nsIFile* *aResult)
1431 : {
1432 19 : if (mProfileDir) {
1433 14 : if (!mProfileNotified)
1434 2 : return NS_ERROR_FAILURE;
1435 :
1436 12 : return mProfileDir->Clone(aResult);
1437 : }
1438 :
1439 5 : if (mAppProvider) {
1440 0 : nsCOMPtr<nsIFile> needsclone;
1441 : bool dummy;
1442 0 : nsresult rv = mAppProvider->GetFile(NS_APP_USER_PROFILE_50_DIR,
1443 : &dummy,
1444 0 : getter_AddRefs(needsclone));
1445 0 : if (NS_SUCCEEDED(rv))
1446 0 : return needsclone->Clone(aResult);
1447 : }
1448 :
1449 5 : return NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, aResult);
1450 : }
1451 :
1452 : nsresult
1453 5 : nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal)
1454 : {
1455 : // Copied from nsAppFileLocationProvider (more or less)
1456 : nsresult rv;
1457 10 : nsCOMPtr<nsIFile> localDir;
1458 :
1459 : #if defined(XP_MACOSX)
1460 : FSRef fsRef;
1461 : OSType folderType;
1462 : if (aLocal) {
1463 : folderType = kCachedDataFolderType;
1464 : } else {
1465 : #ifdef MOZ_THUNDERBIRD
1466 : folderType = kDomainLibraryFolderType;
1467 : #else
1468 : folderType = kApplicationSupportFolderType;
1469 : #endif
1470 : }
1471 : OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef);
1472 : NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);
1473 :
1474 : rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(localDir));
1475 : NS_ENSURE_SUCCESS(rv, rv);
1476 :
1477 : nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir);
1478 : NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED);
1479 :
1480 : rv = dirFileMac->InitWithFSRef(&fsRef);
1481 : NS_ENSURE_SUCCESS(rv, rv);
1482 :
1483 : localDir = do_QueryInterface(dirFileMac, &rv);
1484 : #elif defined(XP_IOS)
1485 : nsAutoCString userDir;
1486 : if (GetUIKitDirectory(aLocal, userDir)) {
1487 : rv = NS_NewNativeLocalFile(userDir, true, getter_AddRefs(localDir));
1488 : } else {
1489 : rv = NS_ERROR_FAILURE;
1490 : }
1491 : NS_ENSURE_SUCCESS(rv, rv);
1492 : #elif defined(XP_WIN)
1493 : nsString path;
1494 : if (aLocal) {
1495 : rv = GetShellFolderPath(FOLDERID_LocalAppData, path);
1496 : if (NS_FAILED(rv))
1497 : rv = GetRegWindowsAppDataFolder(aLocal, path);
1498 : }
1499 : if (!aLocal || NS_FAILED(rv)) {
1500 : rv = GetShellFolderPath(FOLDERID_RoamingAppData, path);
1501 : if (NS_FAILED(rv)) {
1502 : if (!aLocal)
1503 : rv = GetRegWindowsAppDataFolder(aLocal, path);
1504 : }
1505 : }
1506 : NS_ENSURE_SUCCESS(rv, rv);
1507 :
1508 : rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir));
1509 : #elif defined(MOZ_WIDGET_GONK)
1510 : rv = NS_NewNativeLocalFile(NS_LITERAL_CSTRING("/data/b2g"), true,
1511 : getter_AddRefs(localDir));
1512 : #elif defined(XP_UNIX)
1513 5 : const char* homeDir = getenv("HOME");
1514 5 : if (!homeDir || !*homeDir)
1515 0 : return NS_ERROR_FAILURE;
1516 :
1517 : #ifdef ANDROID /* We want (ProfD == ProfLD) on Android. */
1518 : aLocal = false;
1519 : #endif
1520 :
1521 5 : if (aLocal) {
1522 : // If $XDG_CACHE_HOME is defined use it, otherwise use $HOME/.cache.
1523 1 : const char* cacheHome = getenv("XDG_CACHE_HOME");
1524 1 : if (cacheHome && *cacheHome) {
1525 0 : rv = NS_NewNativeLocalFile(nsDependentCString(cacheHome), true,
1526 0 : getter_AddRefs(localDir));
1527 : } else {
1528 2 : rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
1529 3 : getter_AddRefs(localDir));
1530 1 : if (NS_SUCCEEDED(rv))
1531 1 : rv = localDir->AppendNative(NS_LITERAL_CSTRING(".cache"));
1532 : }
1533 : } else {
1534 8 : rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
1535 12 : getter_AddRefs(localDir));
1536 : }
1537 : #else
1538 : #error "Don't know how to get product dir on your platform"
1539 : #endif
1540 :
1541 5 : NS_IF_ADDREF(*aFile = localDir);
1542 5 : return rv;
1543 : }
1544 :
1545 : nsresult
1546 0 : nsXREDirProvider::GetSysUserExtensionsDirectory(nsIFile** aFile)
1547 : {
1548 0 : nsCOMPtr<nsIFile> localDir;
1549 0 : nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false);
1550 0 : NS_ENSURE_SUCCESS(rv, rv);
1551 :
1552 0 : rv = AppendSysUserExtensionPath(localDir);
1553 0 : NS_ENSURE_SUCCESS(rv, rv);
1554 :
1555 0 : rv = EnsureDirectoryExists(localDir);
1556 0 : NS_ENSURE_SUCCESS(rv, rv);
1557 :
1558 0 : localDir.forget(aFile);
1559 0 : return NS_OK;
1560 : }
1561 :
1562 : #if defined(XP_UNIX) || defined(XP_MACOSX)
1563 : nsresult
1564 0 : nsXREDirProvider::GetSystemExtensionsDirectory(nsIFile** aFile)
1565 : {
1566 : nsresult rv;
1567 0 : nsCOMPtr<nsIFile> localDir;
1568 :
1569 0 : rv = GetSystemParentDirectory(getter_AddRefs(localDir));
1570 0 : if (NS_SUCCEEDED(rv)) {
1571 0 : NS_NAMED_LITERAL_CSTRING(sExtensions,
1572 : #if defined(XP_MACOSX)
1573 : "Extensions"
1574 : #else
1575 : "extensions"
1576 : #endif
1577 : );
1578 :
1579 0 : rv = localDir->AppendNative(sExtensions);
1580 0 : if (NS_SUCCEEDED(rv)) {
1581 0 : localDir.forget(aFile);
1582 : }
1583 : }
1584 0 : return rv;
1585 : }
1586 : #endif
1587 :
1588 : nsresult
1589 5 : nsXREDirProvider::GetUserDataDirectory(nsIFile** aFile, bool aLocal,
1590 : const nsACString* aProfileName,
1591 : const nsACString* aAppName,
1592 : const nsACString* aVendorName)
1593 : {
1594 10 : nsCOMPtr<nsIFile> localDir;
1595 5 : nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), aLocal);
1596 5 : NS_ENSURE_SUCCESS(rv, rv);
1597 :
1598 5 : rv = AppendProfilePath(localDir, aProfileName, aAppName, aVendorName, aLocal);
1599 5 : NS_ENSURE_SUCCESS(rv, rv);
1600 :
1601 : #ifdef DEBUG_jungshik
1602 : nsAutoCString cwd;
1603 : localDir->GetNativePath(cwd);
1604 : printf("nsXREDirProvider::GetUserDataDirectory: %s\n", cwd.get());
1605 : #endif
1606 5 : rv = EnsureDirectoryExists(localDir);
1607 5 : NS_ENSURE_SUCCESS(rv, rv);
1608 :
1609 5 : localDir.forget(aFile);
1610 5 : return NS_OK;
1611 : }
1612 :
1613 : nsresult
1614 7 : nsXREDirProvider::EnsureDirectoryExists(nsIFile* aDirectory)
1615 : {
1616 : bool exists;
1617 7 : nsresult rv = aDirectory->Exists(&exists);
1618 7 : NS_ENSURE_SUCCESS(rv, rv);
1619 : #ifdef DEBUG_jungshik
1620 : if (!exists) {
1621 : nsAutoCString cwd;
1622 : aDirectory->GetNativePath(cwd);
1623 : printf("nsXREDirProvider::EnsureDirectoryExists: %s does not\n", cwd.get());
1624 : }
1625 : #endif
1626 7 : if (!exists)
1627 0 : rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0700);
1628 : #ifdef DEBUG_jungshik
1629 : if (NS_FAILED(rv))
1630 : NS_WARNING("nsXREDirProvider::EnsureDirectoryExists: create failed");
1631 : #endif
1632 :
1633 7 : return rv;
1634 : }
1635 :
1636 : nsresult
1637 0 : nsXREDirProvider::AppendSysUserExtensionPath(nsIFile* aFile)
1638 : {
1639 0 : NS_ASSERTION(aFile, "Null pointer!");
1640 :
1641 : nsresult rv;
1642 :
1643 : #if defined (XP_MACOSX) || defined(XP_WIN)
1644 :
1645 : static const char* const sXR = "Mozilla";
1646 : rv = aFile->AppendNative(nsDependentCString(sXR));
1647 : NS_ENSURE_SUCCESS(rv, rv);
1648 :
1649 : static const char* const sExtensions = "Extensions";
1650 : rv = aFile->AppendNative(nsDependentCString(sExtensions));
1651 : NS_ENSURE_SUCCESS(rv, rv);
1652 :
1653 : #elif defined(XP_UNIX)
1654 :
1655 : static const char* const sXR = ".mozilla";
1656 0 : rv = aFile->AppendNative(nsDependentCString(sXR));
1657 0 : NS_ENSURE_SUCCESS(rv, rv);
1658 :
1659 : static const char* const sExtensions = "extensions";
1660 0 : rv = aFile->AppendNative(nsDependentCString(sExtensions));
1661 0 : NS_ENSURE_SUCCESS(rv, rv);
1662 :
1663 : #else
1664 : #error "Don't know how to get XRE user extension path on your platform"
1665 : #endif
1666 0 : return NS_OK;
1667 : }
1668 :
1669 :
1670 : nsresult
1671 5 : nsXREDirProvider::AppendProfilePath(nsIFile* aFile,
1672 : const nsACString* aProfileName,
1673 : const nsACString* aAppName,
1674 : const nsACString* aVendorName,
1675 : bool aLocal)
1676 : {
1677 5 : NS_ASSERTION(aFile, "Null pointer!");
1678 :
1679 5 : if (!gAppData) {
1680 0 : return NS_ERROR_FAILURE;
1681 : }
1682 :
1683 10 : nsAutoCString profile;
1684 10 : nsAutoCString appName;
1685 10 : nsAutoCString vendor;
1686 5 : if (aProfileName && !aProfileName->IsEmpty()) {
1687 0 : profile = *aProfileName;
1688 5 : } else if (aAppName) {
1689 0 : appName = *aAppName;
1690 0 : if (aVendorName) {
1691 0 : vendor = *aVendorName;
1692 : }
1693 5 : } else if (gAppData->profile) {
1694 0 : profile = gAppData->profile;
1695 : } else {
1696 5 : appName = gAppData->name;
1697 5 : vendor = gAppData->vendor;
1698 : }
1699 :
1700 : nsresult rv;
1701 :
1702 : #if defined (XP_MACOSX)
1703 : if (!profile.IsEmpty()) {
1704 : rv = AppendProfileString(aFile, profile.get());
1705 : }
1706 : else {
1707 : // Note that MacOS ignores the vendor when creating the profile hierarchy -
1708 : // all application preferences directories live alongside one another in
1709 : // ~/Library/Application Support/
1710 : rv = aFile->AppendNative(appName);
1711 : }
1712 : NS_ENSURE_SUCCESS(rv, rv);
1713 :
1714 : #elif defined(XP_WIN)
1715 : if (!profile.IsEmpty()) {
1716 : rv = AppendProfileString(aFile, profile.get());
1717 : }
1718 : else {
1719 : if (!vendor.IsEmpty()) {
1720 : rv = aFile->AppendNative(vendor);
1721 : NS_ENSURE_SUCCESS(rv, rv);
1722 : }
1723 : rv = aFile->AppendNative(appName);
1724 : }
1725 : NS_ENSURE_SUCCESS(rv, rv);
1726 :
1727 : #elif defined(ANDROID)
1728 : // The directory used for storing profiles
1729 : // The parent of this directory is set in GetUserDataDirectoryHome
1730 : // XXX: handle gAppData->profile properly
1731 : // XXXsmaug ...and the rest of the profile creation!
1732 : MOZ_ASSERT(!aAppName,
1733 : "Profile creation for external applications is not implemented!");
1734 : rv = aFile->AppendNative(nsDependentCString("mozilla"));
1735 : NS_ENSURE_SUCCESS(rv, rv);
1736 : #elif defined(XP_UNIX)
1737 10 : nsAutoCString folder;
1738 : // Make it hidden (by starting with "."), except when local (the
1739 : // profile is already under ~/.cache or XDG_CACHE_HOME).
1740 5 : if (!aLocal)
1741 4 : folder.Assign('.');
1742 :
1743 5 : if (!profile.IsEmpty()) {
1744 : // Skip any leading path characters
1745 0 : const char* profileStart = profile.get();
1746 0 : while (*profileStart == '/' || *profileStart == '\\')
1747 0 : profileStart++;
1748 :
1749 : // On the off chance that someone wanted their folder to be hidden don't
1750 : // let it become ".."
1751 0 : if (*profileStart == '.' && !aLocal)
1752 0 : profileStart++;
1753 :
1754 0 : folder.Append(profileStart);
1755 0 : ToLowerCase(folder);
1756 :
1757 0 : rv = AppendProfileString(aFile, folder.BeginReading());
1758 : }
1759 : else {
1760 5 : if (!vendor.IsEmpty()) {
1761 5 : folder.Append(vendor);
1762 5 : ToLowerCase(folder);
1763 :
1764 5 : rv = aFile->AppendNative(folder);
1765 5 : NS_ENSURE_SUCCESS(rv, rv);
1766 :
1767 5 : folder.Truncate();
1768 : }
1769 :
1770 5 : folder.Append(appName);
1771 5 : ToLowerCase(folder);
1772 :
1773 5 : rv = aFile->AppendNative(folder);
1774 : }
1775 5 : NS_ENSURE_SUCCESS(rv, rv);
1776 :
1777 : #else
1778 : #error "Don't know how to get profile path on your platform"
1779 : #endif
1780 5 : return NS_OK;
1781 : }
1782 :
1783 : nsresult
1784 0 : nsXREDirProvider::AppendProfileString(nsIFile* aFile, const char* aPath)
1785 : {
1786 0 : NS_ASSERTION(aFile, "Null file!");
1787 0 : NS_ASSERTION(aPath, "Null path!");
1788 :
1789 0 : nsAutoCString pathDup(aPath);
1790 :
1791 0 : char* path = pathDup.BeginWriting();
1792 :
1793 : nsresult rv;
1794 : char* subdir;
1795 0 : while ((subdir = NS_strtok("/\\", &path))) {
1796 0 : rv = aFile->AppendNative(nsDependentCString(subdir));
1797 0 : NS_ENSURE_SUCCESS(rv, rv);
1798 : }
1799 :
1800 0 : return NS_OK;
1801 : }
|