Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp
Warning:line 1949, column 5
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_toolkit_profile0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/toolkit/profile -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/toolkit/profile -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_APP_NAME="firefox" -D MOZ_APP_BASENAME="Firefox" -D MOZ_CREATE_LEGACY_PROFILE -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/toolkit/profile -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/xre -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-16-034744-15991-1 -x c++ Unified_cpp_toolkit_profile0.cpp
1/* -*- Mode: C++; tab-width: 8; 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 "mozilla/ArrayUtils.h"
7#include "mozilla/ScopeExit.h"
8#include "mozilla/UniquePtr.h"
9#include "mozilla/UniquePtrExtensions.h"
10#include "mozilla/WidgetUtils.h"
11#include "nsProfileLock.h"
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <prprf.h>
16#include <prtime.h>
17
18#ifdef XP_WIN
19# include <windows.h>
20# include <shlobj.h>
21# include "mozilla/PolicyChecks.h"
22#endif
23#ifdef XP_UNIX1
24# include <unistd.h>
25#endif
26
27#include "nsToolkitProfileService.h"
28#include "CmdLineAndEnvUtils.h"
29#include "nsIFile.h"
30
31#ifdef XP_MACOSX
32# include <CoreFoundation/CoreFoundation.h>
33# include "nsILocalFileMac.h"
34#endif
35
36#ifdef MOZ_WIDGET_GTK1
37# include "mozilla/WidgetUtilsGtk.h"
38#endif
39
40#include "nsAppDirectoryServiceDefs.h"
41#include "nsDirectoryServiceDefs.h"
42#include "nsNetCID.h"
43#include "nsXULAppAPI.h"
44#include "nsThreadUtils.h"
45
46#include "nsIRunnable.h"
47#include "nsXREDirProvider.h"
48#include "nsAppRunner.h"
49#include "nsString.h"
50#include "nsReadableUtils.h"
51#include "nsNativeCharsetUtils.h"
52#include "mozilla/Attributes.h"
53#include "mozilla/Sprintf.h"
54#include "nsPrintfCString.h"
55#include "mozilla/UniquePtr.h"
56#include "nsIToolkitShellService.h"
57#include "mozilla/Telemetry.h"
58#include "nsProxyRelease.h"
59#include "prinrval.h"
60#include "prthread.h"
61#ifdef MOZ_BACKGROUNDTASKS1
62# include "mozilla/BackgroundTasks.h"
63# include "SpecialSystemDirectory.h"
64#endif
65
66using namespace mozilla;
67
68#define DEV_EDITION_NAME"dev-edition-default" "dev-edition-default"
69#define DEFAULT_NAME"default" "default"
70#define COMPAT_FILEu"compatibility.ini"_ns u"compatibility.ini"_ns
71#define PROFILE_DB_VERSION"2" "2"
72#define INSTALL_PREFIX"Install" "Install"
73#define INSTALL_PREFIX_LENGTH7 7
74
75struct KeyValue {
76 KeyValue(const char* aKey, const char* aValue) : key(aKey), value(aValue) {}
77
78 nsCString key;
79 nsCString value;
80};
81
82static bool GetStrings(const char* aString, const char* aValue,
83 void* aClosure) {
84 nsTArray<UniquePtr<KeyValue>>* array =
85 static_cast<nsTArray<UniquePtr<KeyValue>>*>(aClosure);
86 array->AppendElement(MakeUnique<KeyValue>(aString, aValue));
87
88 return true;
89}
90
91/**
92 * Returns an array of the strings inside a section of an ini file.
93 */
94nsTArray<UniquePtr<KeyValue>> GetSectionStrings(nsINIParsernsINIParser_internal* aParser,
95 const char* aSection) {
96 nsTArray<UniquePtr<KeyValue>> result;
97 aParser->GetStrings(aSection, &GetStrings, &result);
98 return result;
99}
100
101void RemoveProfileRecursion(const nsCOMPtr<nsIFile>& aDirectoryOrFile,
102 bool aIsIgnoreRoot, bool aIsIgnoreLockfile,
103 nsTArray<nsCOMPtr<nsIFile>>& aOutUndeletedFiles) {
104 auto guardDeletion = MakeScopeExit(
105 [&] { aOutUndeletedFiles.AppendElement(aDirectoryOrFile); });
106
107 // We actually would not expect to see links in our profiles, but still.
108 bool isLink = false;
109 NS_ENSURE_SUCCESS_VOID(aDirectoryOrFile->IsSymlink(&isLink))do { nsresult __rv = aDirectoryOrFile->IsSymlink(&isLink
); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0))
)) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla
::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "aDirectoryOrFile->IsSymlink(&isLink)"
, static_cast<uint32_t>(__rv), name ? " (" : "", name ?
name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING,
msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 109); return; } } while (false)
;
110
111 // Only check to see if we have a directory if it isn't a link.
112 bool isDir = false;
113 if (!isLink) {
114 NS_ENSURE_SUCCESS_VOID(aDirectoryOrFile->IsDirectory(&isDir))do { nsresult __rv = aDirectoryOrFile->IsDirectory(&isDir
); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0))
)) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla
::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "aDirectoryOrFile->IsDirectory(&isDir)"
, static_cast<uint32_t>(__rv), name ? " (" : "", name ?
name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING,
msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 114); return; } } while (false)
;
115 }
116
117 if (isDir) {
118 nsCOMPtr<nsIDirectoryEnumerator> dirEnum;
119 NS_ENSURE_SUCCESS_VOID(do { nsresult __rv = aDirectoryOrFile->GetDirectoryEntries
(getter_AddRefs(dirEnum)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "aDirectoryOrFile->GetDirectoryEntries(getter_AddRefs(dirEnum))"
, static_cast<uint32_t>(__rv), name ? " (" : "", name ?
name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING,
msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 120); return; } } while (false)
120 aDirectoryOrFile->GetDirectoryEntries(getter_AddRefs(dirEnum)))do { nsresult __rv = aDirectoryOrFile->GetDirectoryEntries
(getter_AddRefs(dirEnum)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "aDirectoryOrFile->GetDirectoryEntries(getter_AddRefs(dirEnum))"
, static_cast<uint32_t>(__rv), name ? " (" : "", name ?
name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING,
msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 120); return; } } while (false)
;
121
122 bool more = false;
123 while (NS_SUCCEEDED(dirEnum->HasMoreElements(&more))((bool)(__builtin_expect(!!(!NS_FAILED_impl(dirEnum->HasMoreElements
(&more))), 1)))
&& more) {
124 nsCOMPtr<nsISupports> item;
125 dirEnum->GetNext(getter_AddRefs(item));
126 nsCOMPtr<nsIFile> file = do_QueryInterface(item);
127 if (file) {
128 // Do not delete the profile lock.
129 if (aIsIgnoreLockfile && nsProfileLock::IsMaybeLockFile(file)) continue;
130 // If some children's remove fails, we still continue the loop.
131 RemoveProfileRecursion(file, false, false, aOutUndeletedFiles);
132 }
133 }
134 }
135 // Do not delete the root directory (yet).
136 if (!aIsIgnoreRoot) {
137 NS_ENSURE_SUCCESS_VOID(aDirectoryOrFile->Remove(false))do { nsresult __rv = aDirectoryOrFile->Remove(false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0)))) { const
char* name = mozilla::GetStaticErrorName(__rv); mozilla::SmprintfPointer
msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "aDirectoryOrFile->Remove(false)"
, static_cast<uint32_t>(__rv), name ? " (" : "", name ?
name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING,
msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 137); return; } } while (false)
;
138 }
139 guardDeletion.release();
140}
141
142void RemoveProfileFiles(nsIToolkitProfile* aProfile, bool aInBackground) {
143 nsCOMPtr<nsIFile> rootDir;
144 aProfile->GetRootDir(getter_AddRefs(rootDir));
145 nsCOMPtr<nsIFile> localDir;
146 aProfile->GetLocalDir(getter_AddRefs(localDir));
147
148 // XXX If we get here with an active quota manager,
149 // something went very wrong. We want to assert this.
150
151 // Just lock the directories, don't mark the profile as locked or the lock
152 // will attempt to release its reference to the profile on the background
153 // thread which will assert.
154 nsCOMPtr<nsIProfileLock> lock;
155 NS_ENSURE_SUCCESS_VOID(do { nsresult __rv = NS_LockProfilePath(rootDir, localDir, nullptr
, getter_AddRefs(lock)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "NS_LockProfilePath(rootDir, localDir, nullptr, getter_AddRefs(lock))"
, static_cast<uint32_t>(__rv), name ? " (" : "", name ?
name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING,
msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 156); return; } } while (false)
156 NS_LockProfilePath(rootDir, localDir, nullptr, getter_AddRefs(lock)))do { nsresult __rv = NS_LockProfilePath(rootDir, localDir, nullptr
, getter_AddRefs(lock)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "NS_LockProfilePath(rootDir, localDir, nullptr, getter_AddRefs(lock))"
, static_cast<uint32_t>(__rv), name ? " (" : "", name ?
name : "", name ? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING,
msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 156); return; } } while (false)
;
157
158 nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction(
159 "nsToolkitProfile::RemoveProfileFiles",
160 [rootDir, localDir, lock]() mutable {
161 // We try to remove every single file and directory and collect
162 // those whose removal failed.
163 nsTArray<nsCOMPtr<nsIFile>> undeletedFiles;
164 // The root dir might contain the temp dir, so remove the temp dir
165 // first.
166 bool equals;
167 nsresult rv = rootDir->Equals(localDir, &equals);
168 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !equals) {
169 RemoveProfileRecursion(localDir,
170 /* aIsIgnoreRoot */ false,
171 /* aIsIgnoreLockfile */ false, undeletedFiles);
172 }
173 // Now remove the content of the profile dir (except lockfile)
174 RemoveProfileRecursion(rootDir,
175 /* aIsIgnoreRoot */ true,
176 /* aIsIgnoreLockfile */ true, undeletedFiles);
177
178 // Retry loop if something was not deleted
179 if (undeletedFiles.Length() > 0) {
180 uint32_t retries = 1;
181 // XXX: Until bug 1716291 is fixed we just make one retry
182 while (undeletedFiles.Length() > 0 && retries <= 1) {
183 Unused << PR_Sleep(PR_MillisecondsToInterval(10 * retries));
184 for (auto&& file :
185 std::exchange(undeletedFiles, nsTArray<nsCOMPtr<nsIFile>>{})) {
186 RemoveProfileRecursion(file,
187 /* aIsIgnoreRoot */ false,
188 /* aIsIgnoreLockfile */ true,
189 undeletedFiles);
190 }
191 retries++;
192 }
193 }
194
195#ifdef DEBUG1
196 // XXX: Until bug 1716291 is fixed, we do not want to spam release
197 if (undeletedFiles.Length() > 0) {
198 NS_WARNING("Unable to remove all files from the profile directory:")NS_DebugBreak(NS_DEBUG_WARNING, "Unable to remove all files from the profile directory:"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 198)
;
199 // Log the file names of those we could not remove
200 for (auto&& file : undeletedFiles) {
201 nsAutoString leafName;
202 if (NS_SUCCEEDED(file->GetLeafName(leafName))((bool)(__builtin_expect(!!(!NS_FAILED_impl(file->GetLeafName
(leafName))), 1)))
) {
203 NS_WARNING(NS_LossyConvertUTF16toASCII(leafName).get())NS_DebugBreak(NS_DEBUG_WARNING, NS_LossyConvertUTF16toASCII(leafName
).get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 203)
;
204 }
205 }
206 }
207#endif
208 // XXX: Activate this assert once bug 1716291 is fixed
209 // MOZ_ASSERT(undeletedFiles.Length() == 0);
210
211 // Now we can unlock the profile safely.
212 lock->Unlock();
213 // nsIProfileLock is not threadsafe so release our reference to it on
214 // the main thread.
215 NS_ReleaseOnMainThread("nsToolkitProfile::RemoveProfileFiles::Unlock",
216 lock.forget());
217
218 if (undeletedFiles.Length() == 0) {
219 // We can safely remove the (empty) remaining profile directory
220 // and lockfile, no other files are here.
221 // As we do this only if we had no other blockers, this is as safe
222 // as deleting the lockfile explicitely after unlocking.
223 Unused << rootDir->Remove(true);
224 }
225 });
226
227 if (aInBackground) {
228 nsCOMPtr<nsIEventTarget> target =
229 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID"@mozilla.org/network/stream-transport-service;1");
230 target->Dispatch(runnable, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
231 } else {
232 runnable->Run();
233 }
234}
235
236nsToolkitProfile::nsToolkitProfile(const nsACString& aName, nsIFile* aRootDir,
237 nsIFile* aLocalDir, bool aFromDB)
238 : mName(aName),
239 mRootDir(aRootDir),
240 mLocalDir(aLocalDir),
241 mLock(nullptr),
242 mIndex(0),
243 mSection("Profile") {
244 NS_ASSERTION(aRootDir, "No file!")do { if (!(aRootDir)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "No file!"
, "aRootDir", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 244); MOZ_PretendNoReturn(); } } while (0)
;
245
246 RefPtr<nsToolkitProfile> prev =
247 nsToolkitProfileService::gService->mProfiles.getLast();
248 if (prev) {
249 mIndex = prev->mIndex + 1;
250 }
251 mSection.AppendInt(mIndex);
252
253 nsToolkitProfileService::gService->mProfiles.insertBack(this);
254
255 // If this profile isn't in the database already add it.
256 if (!aFromDB) {
257 nsINIParsernsINIParser_internal* db = &nsToolkitProfileService::gService->mProfileDB;
258 db->SetString(mSection.get(), "Name", mName.get());
259
260 bool isRelative = false;
261 nsCString descriptor;
262 nsToolkitProfileService::gService->GetProfileDescriptor(this, descriptor,
263 &isRelative);
264
265 db->SetString(mSection.get(), "IsRelative", isRelative ? "1" : "0");
266 db->SetString(mSection.get(), "Path", descriptor.get());
267 }
268}
269
270NS_IMPL_ISUPPORTS(nsToolkitProfile, nsIToolkitProfile)MozExternalRefCountType nsToolkitProfile::AddRef(void) { static_assert
(!std::is_destructible_v<nsToolkitProfile>, "Reference-counted class "
"nsToolkitProfile" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
270; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsToolkitProfile" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsToolkitProfile" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsToolkitProfile\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsToolkitProfile\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 270; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsToolkitProfile" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsToolkitProfile"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsToolkitProfile::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 270
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsToolkitProfile" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsToolkitProfile" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsToolkitProfile\" != nullptr" " (" "Must specify a name" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsToolkitProfile\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 270; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsToolkitProfile" " not thread-safe"); const
char* const nametmp = "nsToolkitProfile"; nsrefcnt count = --
mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count
== 0) { mRefCnt = 1; delete (this); return 0; } return count
; } nsresult nsToolkitProfile::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 270); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsToolkitProfile, nsIToolkitProfile>,
int32_t( reinterpret_cast<char*>(static_cast<nsIToolkitProfile
*>((nsToolkitProfile*)0x1000)) - reinterpret_cast<char*
>((nsToolkitProfile*)0x1000))}, {&mozilla::detail::kImplementedIID
<nsToolkitProfile, nsISupports>, int32_t(reinterpret_cast
<char*>(static_cast<nsISupports*>( static_cast<
nsIToolkitProfile*>((nsToolkitProfile*)0x1000))) - reinterpret_cast
<char*>((nsToolkitProfile*)0x1000))}, { nullptr, 0 } } ;
static_assert((sizeof(table) / sizeof(table[0])) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
271
272NS_IMETHODIMPnsresult
273nsToolkitProfile::GetRootDir(nsIFile** aResult) {
274 NS_ADDREF(*aResult = mRootDir)(*aResult = mRootDir)->AddRef();
275 return NS_OK;
276}
277
278NS_IMETHODIMPnsresult
279nsToolkitProfile::GetLocalDir(nsIFile** aResult) {
280 NS_ADDREF(*aResult = mLocalDir)(*aResult = mLocalDir)->AddRef();
281 return NS_OK;
282}
283
284NS_IMETHODIMPnsresult
285nsToolkitProfile::GetName(nsACString& aResult) {
286 aResult = mName;
287 return NS_OK;
288}
289
290NS_IMETHODIMPnsresult
291nsToolkitProfile::SetName(const nsACString& aName) {
292 NS_ASSERTION(nsToolkitProfileService::gService, "Where did my service go?")do { if (!(nsToolkitProfileService::gService)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Where did my service go?", "nsToolkitProfileService::gService"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 292); MOZ_PretendNoReturn(); } } while (0)
;
293
294 if (mName.Equals(aName)) {
295 return NS_OK;
296 }
297
298 // Changing the name from the dev-edition default profile name makes this
299 // profile no longer the dev-edition default.
300 if (mName.EqualsLiteral(DEV_EDITION_NAME"dev-edition-default") &&
301 nsToolkitProfileService::gService->mDevEditionDefault == this) {
302 nsToolkitProfileService::gService->mDevEditionDefault = nullptr;
303 }
304
305 mName = aName;
306
307 nsresult rv = nsToolkitProfileService::gService->mProfileDB.SetString(
308 mSection.get(), "Name", mName.get());
309 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 309); return rv; } } while (false)
;
310
311 // Setting the name to the dev-edition default profile name will cause this
312 // profile to become the dev-edition default.
313 if (aName.EqualsLiteral(DEV_EDITION_NAME"dev-edition-default") &&
314 !nsToolkitProfileService::gService->mDevEditionDefault) {
315 nsToolkitProfileService::gService->mDevEditionDefault = this;
316 }
317
318 return NS_OK;
319}
320
321nsresult nsToolkitProfile::RemoveInternal(bool aRemoveFiles,
322 bool aInBackground) {
323 NS_ASSERTION(nsToolkitProfileService::gService, "Whoa, my service is gone.")do { if (!(nsToolkitProfileService::gService)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Whoa, my service is gone.", "nsToolkitProfileService::gService"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 323); MOZ_PretendNoReturn(); } } while (0)
;
324
325 if (mLock) return NS_ERROR_FILE_IS_LOCKED;
326
327 if (!isInList()) {
328 return NS_ERROR_NOT_INITIALIZED;
329 }
330
331 if (aRemoveFiles) {
332 RemoveProfileFiles(this, aInBackground);
333 }
334
335 nsINIParsernsINIParser_internal* db = &nsToolkitProfileService::gService->mProfileDB;
336 db->DeleteSection(mSection.get());
337
338 // We make some assumptions that the profile's index in the database is based
339 // on its position in the linked list. Removing a profile means we have to fix
340 // the index of later profiles in the list. The easiest way to do that is just
341 // to move the last profile into the profile's position and just update its
342 // index.
343 RefPtr<nsToolkitProfile> last =
344 nsToolkitProfileService::gService->mProfiles.getLast();
345 if (last != this) {
346 // Update the section in the db.
347 last->mIndex = mIndex;
348 db->RenameSection(last->mSection.get(), mSection.get());
349 last->mSection = mSection;
350
351 if (last != getNext()) {
352 last->remove();
353 setNext(last);
354 }
355 }
356
357 remove();
358
359 if (nsToolkitProfileService::gService->mNormalDefault == this) {
360 nsToolkitProfileService::gService->mNormalDefault = nullptr;
361 }
362 if (nsToolkitProfileService::gService->mDevEditionDefault == this) {
363 nsToolkitProfileService::gService->mDevEditionDefault = nullptr;
364 }
365 if (nsToolkitProfileService::gService->mDedicatedProfile == this) {
366 nsToolkitProfileService::gService->SetDefaultProfile(nullptr);
367 }
368
369 return NS_OK;
370}
371
372NS_IMETHODIMPnsresult
373nsToolkitProfile::Remove(bool removeFiles) {
374 return RemoveInternal(removeFiles, false /* in background */);
375}
376
377NS_IMETHODIMPnsresult
378nsToolkitProfile::RemoveInBackground(bool removeFiles) {
379 return RemoveInternal(removeFiles, true /* in background */);
380}
381
382NS_IMETHODIMPnsresult
383nsToolkitProfile::Lock(nsIProfileUnlocker** aUnlocker,
384 nsIProfileLock** aResult) {
385 if (mLock) {
386 NS_ADDREF(*aResult = mLock)(*aResult = mLock)->AddRef();
387 return NS_OK;
388 }
389
390 RefPtr<nsToolkitProfileLock> lock = new nsToolkitProfileLock();
391
392 nsresult rv = lock->Init(this, aUnlocker);
393 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
394
395 NS_ADDREF(*aResult = lock)(*aResult = lock)->AddRef();
396 return NS_OK;
397}
398
399NS_IMPL_ISUPPORTS(nsToolkitProfileLock, nsIProfileLock)MozExternalRefCountType nsToolkitProfileLock::AddRef(void) { static_assert
(!std::is_destructible_v<nsToolkitProfileLock>, "Reference-counted class "
"nsToolkitProfileLock" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 399); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
399; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsToolkitProfileLock" != nullptr)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!("nsToolkitProfileLock" != nullptr))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("\"nsToolkitProfileLock\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 399); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsToolkitProfileLock\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 399; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsToolkitProfileLock" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsToolkitProfileLock"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsToolkitProfileLock::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 399); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 399
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsToolkitProfileLock" != nullptr)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!("nsToolkitProfileLock" != nullptr))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("\"nsToolkitProfileLock\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 399); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsToolkitProfileLock\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 399; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsToolkitProfileLock" " not thread-safe"); const
char* const nametmp = "nsToolkitProfileLock"; nsrefcnt count
= --mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (
count == 0) { mRefCnt = 1; delete (this); return 0; } return count
; } nsresult nsToolkitProfileLock::QueryInterface(const nsIID
& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 399); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsToolkitProfileLock, nsIProfileLock>
, int32_t( reinterpret_cast<char*>(static_cast<nsIProfileLock
*>((nsToolkitProfileLock*)0x1000)) - reinterpret_cast<char
*>((nsToolkitProfileLock*)0x1000))}, {&mozilla::detail
::kImplementedIID<nsToolkitProfileLock, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIProfileLock*>((nsToolkitProfileLock*)0x1000
))) - reinterpret_cast<char*>((nsToolkitProfileLock*)0x1000
))}, { nullptr, 0 } } ; static_assert((sizeof(table) / sizeof
(table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
400
401nsresult nsToolkitProfileLock::Init(nsToolkitProfile* aProfile,
402 nsIProfileUnlocker** aUnlocker) {
403 nsresult rv;
404 rv = Init(aProfile->mRootDir, aProfile->mLocalDir, aUnlocker);
405 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) mProfile = aProfile;
406
407 return rv;
408}
409
410nsresult nsToolkitProfileLock::Init(nsIFile* aDirectory,
411 nsIFile* aLocalDirectory,
412 nsIProfileUnlocker** aUnlocker) {
413 nsresult rv;
414
415 rv = mLock.Lock(aDirectory, aUnlocker);
416
417 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
418 mDirectory = aDirectory;
419 mLocalDirectory = aLocalDirectory;
420 }
421
422 return rv;
423}
424
425NS_IMETHODIMPnsresult
426nsToolkitProfileLock::GetDirectory(nsIFile** aResult) {
427 if (!mDirectory) {
428 NS_ERROR("Not initialized, or unlocked!")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Not initialized, or unlocked!"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 428); MOZ_PretendNoReturn(); } while (0)
;
429 return NS_ERROR_NOT_INITIALIZED;
430 }
431
432 NS_ADDREF(*aResult = mDirectory)(*aResult = mDirectory)->AddRef();
433 return NS_OK;
434}
435
436NS_IMETHODIMPnsresult
437nsToolkitProfileLock::GetLocalDirectory(nsIFile** aResult) {
438 if (!mLocalDirectory) {
439 NS_ERROR("Not initialized, or unlocked!")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Not initialized, or unlocked!"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 439); MOZ_PretendNoReturn(); } while (0)
;
440 return NS_ERROR_NOT_INITIALIZED;
441 }
442
443 NS_ADDREF(*aResult = mLocalDirectory)(*aResult = mLocalDirectory)->AddRef();
444 return NS_OK;
445}
446
447NS_IMETHODIMPnsresult
448nsToolkitProfileLock::Unlock() {
449 if (!mDirectory) {
450 NS_ERROR("Unlocking a never-locked nsToolkitProfileLock!")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unlocking a never-locked nsToolkitProfileLock!"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 450); MOZ_PretendNoReturn(); } while (0)
;
451 return NS_ERROR_UNEXPECTED;
452 }
453
454 // XXX If we get here with an active quota manager,
455 // something went very wrong. We want to assert this.
456
457 mLock.Unlock();
458
459 if (mProfile) {
460 mProfile->mLock = nullptr;
461 mProfile = nullptr;
462 }
463 mDirectory = nullptr;
464 mLocalDirectory = nullptr;
465
466 return NS_OK;
467}
468
469NS_IMETHODIMPnsresult
470nsToolkitProfileLock::GetReplacedLockTime(PRTime* aResult) {
471 mLock.GetReplacedLockTime(aResult);
472 return NS_OK;
473}
474
475nsToolkitProfileLock::~nsToolkitProfileLock() {
476 if (mDirectory) {
477 Unlock();
478 }
479}
480
481nsToolkitProfileService* nsToolkitProfileService::gService = nullptr;
482
483NS_IMPL_ISUPPORTS(nsToolkitProfileService, nsIToolkitProfileService)MozExternalRefCountType nsToolkitProfileService::AddRef(void)
{ static_assert(!std::is_destructible_v<nsToolkitProfileService
>, "Reference-counted class " "nsToolkitProfileService" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
483; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsToolkitProfileService" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsToolkitProfileService" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsToolkitProfileService\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsToolkitProfileService\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 483; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsToolkitProfileService" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsToolkitProfileService"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType nsToolkitProfileService::Release
(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 483
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsToolkitProfileService" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsToolkitProfileService" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsToolkitProfileService\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsToolkitProfileService\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 483; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsToolkitProfileService" " not thread-safe"
); const char* const nametmp = "nsToolkitProfileService"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult nsToolkitProfileService::QueryInterface(const
nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 483); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsToolkitProfileService, nsIToolkitProfileService
>, int32_t( reinterpret_cast<char*>(static_cast<nsIToolkitProfileService
*>((nsToolkitProfileService*)0x1000)) - reinterpret_cast<
char*>((nsToolkitProfileService*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsToolkitProfileService, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIToolkitProfileService*>((nsToolkitProfileService
*)0x1000))) - reinterpret_cast<char*>((nsToolkitProfileService
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
484
485nsToolkitProfileService::nsToolkitProfileService()
486 : mStartupProfileSelected(false),
487 mStartWithLast(true),
488 mIsFirstRun(true),
489 mUseDevEditionProfile(false),
490#ifdef MOZ_DEDICATED_PROFILES1
491 mUseDedicatedProfile(!IsSnapEnvironment() && !UseLegacyProfiles()),
492#else
493 mUseDedicatedProfile(false),
494#endif
495 mStartupReason(u"unknown"_ns),
496 mStartupFileVersion("0"_ns),
497 mMaybeLockProfile(false),
498 mUpdateChannel(MOZ_STRINGIFY(MOZ_UPDATE_CHANNEL)"default"),
499 mProfileDBExists(false),
500 mProfileDBFileSize(0),
501 mProfileDBModifiedTime(0) {
502#ifdef MOZ_DEV_EDITION
503 mUseDevEditionProfile = true;
504#endif
505}
506
507nsToolkitProfileService::~nsToolkitProfileService() {
508 gService = nullptr;
509 mProfiles.clear();
510}
511
512void nsToolkitProfileService::CompleteStartup() {
513 if (!mStartupProfileSelected) {
514 return;
515 }
516
517 ScalarSet(mozilla::Telemetry::ScalarID::STARTUP_PROFILE_SELECTION_REASON,
518 mStartupReason);
519 ScalarSet(mozilla::Telemetry::ScalarID::STARTUP_PROFILE_DATABASE_VERSION,
520 NS_ConvertUTF8toUTF16(mStartupFileVersion));
521 ScalarSet(mozilla::Telemetry::ScalarID::STARTUP_PROFILE_COUNT,
522 static_cast<uint32_t>(mProfiles.length()));
523
524 if (mMaybeLockProfile) {
525 nsCOMPtr<nsIToolkitShellService> shell =
526 do_GetService(NS_TOOLKITSHELLSERVICE_CONTRACTID"@mozilla.org/toolkit/shell-service;1");
527 if (!shell) {
528 return;
529 }
530
531 bool isDefaultApp;
532 nsresult rv = shell->IsDefaultApplication(&isDefaultApp);
533 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 533); return; } } while (false)
;
534
535 if (isDefaultApp) {
536 mProfileDB.SetString(mInstallSection.get(), "Locked", "1");
537
538 // There is a very small chance that this could fail if something else
539 // overwrote the profiles database since we started up, probably less than
540 // a second ago. There isn't really a sane response here, all the other
541 // profile changes are already flushed so whether we fail to flush here or
542 // force quit the app makes no difference.
543 NS_ENSURE_SUCCESS_VOID(Flush())do { nsresult __rv = Flush(); if (((bool)(__builtin_expect(!!
(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "Flush()", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 543); return; } } while (false)
;
544 }
545 }
546}
547
548// Tests whether the passed profile was last used by this install.
549bool nsToolkitProfileService::IsProfileForCurrentInstall(
550 nsIToolkitProfile* aProfile) {
551 nsCOMPtr<nsIFile> profileDir;
552 nsresult rv = aProfile->GetRootDir(getter_AddRefs(profileDir));
553 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 553); return false; } } while (false)
;
554
555 nsCOMPtr<nsIFile> compatFile;
556 rv = profileDir->Clone(getter_AddRefs(compatFile));
557 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 557); return false; } } while (false)
;
558
559 rv = compatFile->Append(COMPAT_FILEu"compatibility.ini"_ns);
560 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 560); return false; } } while (false)
;
561
562 nsINIParsernsINIParser_internal compatData;
563 rv = compatData.Init(compatFile);
564 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 564); return false; } } while (false)
;
565
566 /**
567 * In xpcshell gDirServiceProvider doesn't have all the correct directories
568 * set so using NS_GetSpecialDirectory works better there. But in a normal
569 * app launch the component registry isn't initialized so
570 * NS_GetSpecialDirectory doesn't work. So we have to use two different
571 * paths to support testing.
572 */
573 nsCOMPtr<nsIFile> currentGreDir;
574 rv = NS_GetSpecialDirectory(NS_GRE_DIR"GreD", getter_AddRefs(currentGreDir));
575 if (rv == NS_ERROR_NOT_INITIALIZED) {
576 currentGreDir = gDirServiceProvider->GetGREDir();
577 MOZ_ASSERT(currentGreDir, "No GRE dir found.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(currentGreDir)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(currentGreDir))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("currentGreDir" " ("
"No GRE dir found." ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 577); AnnotateMozCrashReason("MOZ_ASSERT" "(" "currentGreDir"
") (" "No GRE dir found." ")"); do { *((volatile int*)__null
) = 577; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
578 } else if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
579 return false;
580 }
581
582 nsCString lastGreDirStr;
583 rv = compatData.GetString("Compatibility", "LastPlatformDir", lastGreDirStr);
584 // If this string is missing then this profile is from an ancient version.
585 // We'll opt to use it in this case.
586 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
587 return true;
588 }
589
590 nsCOMPtr<nsIFile> lastGreDir;
591 rv = NS_NewNativeLocalFile(""_ns, false, getter_AddRefs(lastGreDir));
592 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 592); return false; } } while (false)
;
593
594 rv = lastGreDir->SetPersistentDescriptor(lastGreDirStr);
595 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 595); return false; } } while (false)
;
596
597#ifdef XP_WIN
598# if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
599 mozilla::PathString lastGreDirPath, currentGreDirPath;
600 lastGreDirPath = lastGreDir->NativePath();
601 currentGreDirPath = currentGreDir->NativePath();
602 if (lastGreDirPath.Equals(currentGreDirPath,
603 nsCaseInsensitiveStringComparator)) {
604 return true;
605 }
606
607 // Convert a 64-bit install path to what would have been the 32-bit install
608 // path to allow users to migrate their profiles from one to the other.
609 PWSTR pathX86 = nullptr;
610 HRESULT hres =
611 SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, 0, nullptr, &pathX86);
612 if (SUCCEEDED(hres)) {
613 nsDependentString strPathX86(pathX86);
614 if (!StringBeginsWith(currentGreDirPath, strPathX86,
615 nsCaseInsensitiveStringComparator)) {
616 PWSTR path = nullptr;
617 hres = SHGetKnownFolderPath(FOLDERID_ProgramFiles, 0, nullptr, &path);
618 if (SUCCEEDED(hres)) {
619 if (StringBeginsWith(currentGreDirPath, nsDependentString(path),
620 nsCaseInsensitiveStringComparator)) {
621 currentGreDirPath.Replace(0, wcslen(path), strPathX86);
622 }
623 }
624 CoTaskMemFree(path);
625 }
626 }
627 CoTaskMemFree(pathX86);
628
629 return lastGreDirPath.Equals(currentGreDirPath,
630 nsCaseInsensitiveStringComparator);
631# endif
632#endif
633
634 bool equal;
635 rv = lastGreDir->Equals(currentGreDir, &equal);
636 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 636); return false; } } while (false)
;
637
638 return equal;
639}
640
641/**
642 * Used the first time an install with dedicated profile support runs. Decides
643 * whether to mark the passed profile as the default for this install.
644 *
645 * The goal is to reduce disruption but ideally end up with the OS default
646 * install using the old default profile.
647 *
648 * If the decision is to use the profile then it will be unassigned as the
649 * dedicated default for other installs.
650 *
651 * We won't attempt to use the profile if it was last used by a different
652 * install.
653 *
654 * If the profile is currently in use by an install that was either the OS
655 * default install or the profile has been explicitely chosen by some other
656 * means then we won't use it.
657 *
658 * aResult will be set to true if we chose to make the profile the new dedicated
659 * default.
660 */
661nsresult nsToolkitProfileService::MaybeMakeDefaultDedicatedProfile(
662 nsIToolkitProfile* aProfile, bool* aResult) {
663 nsresult rv;
664 *aResult = false;
665
666 // If the profile was last used by a different install then we won't use it.
667 if (!IsProfileForCurrentInstall(aProfile)) {
668 return NS_OK;
669 }
670
671 nsCString descriptor;
672 rv = GetProfileDescriptor(aProfile, descriptor, nullptr);
673 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 673); return rv; } } while (false)
;
674
675 // Get a list of all the installs.
676 nsTArray<nsCString> installs = GetKnownInstalls();
677
678 // Cache the installs that use the profile.
679 nsTArray<nsCString> inUseInstalls;
680
681 // See if the profile is already in use by an install that hasn't locked it.
682 for (uint32_t i = 0; i < installs.Length(); i++) {
683 const nsCString& install = installs[i];
684
685 nsCString path;
686 rv = mProfileDB.GetString(install.get(), "Default", path);
687 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
688 continue;
689 }
690
691 // Is this install using the profile we care about?
692 if (!descriptor.Equals(path)) {
693 continue;
694 }
695
696 // Is this profile locked to this other install?
697 nsCString isLocked;
698 rv = mProfileDB.GetString(install.get(), "Locked", isLocked);
699 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && isLocked.Equals("1")) {
700 return NS_OK;
701 }
702
703 inUseInstalls.AppendElement(install);
704 }
705
706 // At this point we've decided to take the profile. Strip it from other
707 // installs.
708 for (uint32_t i = 0; i < inUseInstalls.Length(); i++) {
709 // Removing the default setting entirely will make the install go through
710 // the first run process again at startup and create itself a new profile.
711 mProfileDB.DeleteString(inUseInstalls[i].get(), "Default");
712 }
713
714 // Set this as the default profile for this install.
715 SetDefaultProfile(aProfile);
716
717 // SetDefaultProfile will have locked this profile to this install so no
718 // other installs will steal it, but this was auto-selected so we want to
719 // unlock it so that other installs can potentially take it.
720 mProfileDB.DeleteString(mInstallSection.get(), "Locked");
721
722 // Persist the changes.
723 rv = Flush();
724 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 724); return rv; } } while (false)
;
725
726 // Once XPCOM is available check if this is the default application and if so
727 // lock the profile again.
728 mMaybeLockProfile = true;
729 *aResult = true;
730
731 return NS_OK;
732}
733
734bool IsFileOutdated(nsIFile* aFile, bool aExists, PRTime aLastModified,
735 int64_t aLastSize) {
736 nsCOMPtr<nsIFile> file;
737 nsresult rv = aFile->Clone(getter_AddRefs(file));
738 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
739 return false;
740 }
741
742 bool exists;
743 rv = aFile->Exists(&exists);
744 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || exists != aExists) {
745 return true;
746 }
747
748 if (!exists) {
749 return false;
750 }
751
752 int64_t size;
753 rv = aFile->GetFileSize(&size);
754 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || size != aLastSize) {
755 return true;
756 }
757
758 PRTime time;
759 rv = aFile->GetLastModifiedTime(&time);
760 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || time != aLastModified) {
761 return true;
762 }
763
764 return false;
765}
766
767nsresult UpdateFileStats(nsIFile* aFile, bool* aExists, PRTime* aLastModified,
768 int64_t* aLastSize) {
769 nsCOMPtr<nsIFile> file;
770 nsresult rv = aFile->Clone(getter_AddRefs(file));
771 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 771); return rv; } } while (false)
;
772
773 rv = file->Exists(aExists);
774 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 774); return rv; } } while (false)
;
775
776 if (!(*aExists)) {
777 *aLastModified = 0;
778 *aLastSize = 0;
779 return NS_OK;
780 }
781
782 rv = file->GetFileSize(aLastSize);
783 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 783); return rv; } } while (false)
;
784
785 rv = file->GetLastModifiedTime(aLastModified);
786 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 786); return rv; } } while (false)
;
787
788 return NS_OK;
789}
790
791NS_IMETHODIMPnsresult
792nsToolkitProfileService::GetIsListOutdated(bool* aResult) {
793 if (IsFileOutdated(mProfileDBFile, mProfileDBExists, mProfileDBModifiedTime,
794 mProfileDBFileSize)) {
795 *aResult = true;
796 return NS_OK;
797 }
798
799 *aResult = false;
800 return NS_OK;
801}
802
803struct ImportInstallsClosure {
804 nsINIParsernsINIParser_internal* backupData;
805 nsINIParsernsINIParser_internal* profileDB;
806};
807
808static bool ImportInstalls(const char* aSection, void* aClosure) {
809 ImportInstallsClosure* closure =
810 static_cast<ImportInstallsClosure*>(aClosure);
811
812 nsTArray<UniquePtr<KeyValue>> strings =
813 GetSectionStrings(closure->backupData, aSection);
814 if (strings.IsEmpty()) {
815 return true;
816 }
817
818 nsCString newSection(INSTALL_PREFIX"Install");
819 newSection.Append(aSection);
820 nsCString buffer;
821
822 for (uint32_t i = 0; i < strings.Length(); i++) {
823 closure->profileDB->SetString(newSection.get(), strings[i]->key.get(),
824 strings[i]->value.get());
825 }
826
827 return true;
828}
829
830nsresult nsToolkitProfileService::Init() {
831 NS_ASSERTION(gDirServiceProvider, "No dirserviceprovider!")do { if (!(gDirServiceProvider)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "No dirserviceprovider!", "gDirServiceProvider", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 831); MOZ_PretendNoReturn(); } } while (0)
;
832 nsresult rv;
833
834 rv = nsXREDirProvider::GetUserAppDataDirectory(getter_AddRefs(mAppData));
835 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 835); return rv; } } while (false)
;
836
837 rv = nsXREDirProvider::GetUserLocalDataDirectory(getter_AddRefs(mTempData));
838 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 838); return rv; } } while (false)
;
839
840 rv = mAppData->Clone(getter_AddRefs(mProfileDBFile));
841 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 841); return rv; } } while (false)
;
842
843 rv = mProfileDBFile->AppendNative("profiles.ini"_ns);
844 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 844); return rv; } } while (false)
;
845
846 rv = mAppData->Clone(getter_AddRefs(mInstallDBFile));
847 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 847); return rv; } } while (false)
;
848
849 rv = mInstallDBFile->AppendNative("installs.ini"_ns);
850 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 850); return rv; } } while (false)
;
851
852 nsAutoCString buffer;
853
854 rv = UpdateFileStats(mProfileDBFile, &mProfileDBExists,
855 &mProfileDBModifiedTime, &mProfileDBFileSize);
856 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && mProfileDBExists) {
857 rv = mProfileDB.Init(mProfileDBFile);
858 // Init does not fail on parsing errors, only on OOM/really unexpected
859 // conditions.
860 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
861 return rv;
862 }
863
864 rv = mProfileDB.GetString("General", "StartWithLastProfile", buffer);
865 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
866 mStartWithLast = !buffer.EqualsLiteral("0");
867 }
868
869 rv = mProfileDB.GetString("General", "Version", mStartupFileVersion);
870 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
871 // This is a profiles.ini written by an older version. We must restore
872 // any install data from the backup. We consider this old format to be
873 // a version 1 file.
874 mStartupFileVersion.AssignLiteral("1");
875 nsINIParsernsINIParser_internal installDB;
876
877 if (NS_SUCCEEDED(installDB.Init(mInstallDBFile))((bool)(__builtin_expect(!!(!NS_FAILED_impl(installDB.Init(mInstallDBFile
))), 1)))
) {
878 // There is install data to import.
879 ImportInstallsClosure closure = {&installDB, &mProfileDB};
880 installDB.GetSections(&ImportInstalls, &closure);
881 }
882
883 rv = mProfileDB.SetString("General", "Version", PROFILE_DB_VERSION"2");
884 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 884); return rv; } } while (false)
;
885 }
886 } else {
887 rv = mProfileDB.SetString("General", "StartWithLastProfile",
888 mStartWithLast ? "1" : "0");
889 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 889); return rv; } } while (false)
;
890 rv = mProfileDB.SetString("General", "Version", PROFILE_DB_VERSION"2");
891 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 891); return rv; } } while (false)
;
892 }
893
894 nsCString installProfilePath;
895
896 if (mUseDedicatedProfile) {
897 nsString installHash;
898 rv = gDirServiceProvider->GetInstallHash(installHash);
899 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 899); return rv; } } while (false)
;
900 CopyUTF16toUTF8(installHash, mInstallSection);
901 mInstallSection.Insert(INSTALL_PREFIX"Install", 0);
902
903 // Try to find the descriptor for the default profile for this install.
904 rv = mProfileDB.GetString(mInstallSection.get(), "Default",
905 installProfilePath);
906
907 // Not having a value means this install doesn't appear in installs.ini so
908 // this is the first run for this install.
909 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
910 mIsFirstRun = true;
911
912 // Gets the install section that would have been created if the install
913 // path has incorrect casing (see bug 1555319). We use this later during
914 // profile selection.
915 rv = gDirServiceProvider->GetLegacyInstallHash(installHash);
916 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 916); return rv; } } while (false)
;
917 CopyUTF16toUTF8(installHash, mLegacyInstallSection);
918 mLegacyInstallSection.Insert(INSTALL_PREFIX"Install", 0);
919 } else {
920 mIsFirstRun = false;
921 }
922 }
923
924 nsToolkitProfile* currentProfile = nullptr;
925
926#ifdef MOZ_DEV_EDITION
927 nsCOMPtr<nsIFile> ignoreDevEditionProfile;
928 rv = mAppData->Clone(getter_AddRefs(ignoreDevEditionProfile));
929 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
930 return rv;
931 }
932
933 rv = ignoreDevEditionProfile->AppendNative("ignore-dev-edition-profile"_ns);
934 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
935 return rv;
936 }
937
938 bool shouldIgnoreSeparateProfile;
939 rv = ignoreDevEditionProfile->Exists(&shouldIgnoreSeparateProfile);
940 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
941
942 mUseDevEditionProfile = !shouldIgnoreSeparateProfile;
943#endif
944
945 nsCOMPtr<nsIToolkitProfile> autoSelectProfile;
946
947 unsigned int nonDevEditionProfiles = 0;
948 unsigned int c = 0;
949 for (c = 0; true; ++c) {
950 nsAutoCString profileID("Profile");
951 profileID.AppendInt(c);
952
953 rv = mProfileDB.GetString(profileID.get(), "IsRelative", buffer);
954 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) break;
955
956 bool isRelative = buffer.EqualsLiteral("1");
957
958 nsAutoCString filePath;
959
960 rv = mProfileDB.GetString(profileID.get(), "Path", filePath);
961 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
962 NS_ERROR("Malformed profiles.ini: Path= not found")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Malformed profiles.ini: Path= not found"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 962); MOZ_PretendNoReturn(); } while (0)
;
963 continue;
964 }
965
966 nsAutoCString name;
967
968 rv = mProfileDB.GetString(profileID.get(), "Name", name);
969 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
970 NS_ERROR("Malformed profiles.ini: Name= not found")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Malformed profiles.ini: Name= not found"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 970); MOZ_PretendNoReturn(); } while (0)
;
971 continue;
972 }
973
974 nsCOMPtr<nsIFile> rootDir;
975 rv = NS_NewNativeLocalFile(""_ns, true, getter_AddRefs(rootDir));
976 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 976); return rv; } } while (false)
;
977
978 if (isRelative) {
979 rv = rootDir->SetRelativeDescriptor(mAppData, filePath);
980 } else {
981 rv = rootDir->SetPersistentDescriptor(filePath);
982 }
983 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) continue;
984
985 nsCOMPtr<nsIFile> localDir;
986 if (isRelative) {
987 rv = NS_NewNativeLocalFile(""_ns, true, getter_AddRefs(localDir));
988 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 988); return rv; } } while (false)
;
989
990 rv = localDir->SetRelativeDescriptor(mTempData, filePath);
991 } else {
992 localDir = rootDir;
993 }
994
995 currentProfile = new nsToolkitProfile(name, rootDir, localDir, true);
996
997 // If a user has modified the ini file path it may make for a valid profile
998 // path but not match what we would have serialised and so may not match
999 // the path in the install section. Re-serialise it to get it in the
1000 // expected form again.
1001 bool nowRelative;
1002 nsCString descriptor;
1003 GetProfileDescriptor(currentProfile, descriptor, &nowRelative);
1004
1005 if (isRelative != nowRelative || !descriptor.Equals(filePath)) {
1006 mProfileDB.SetString(profileID.get(), "IsRelative",
1007 nowRelative ? "1" : "0");
1008 mProfileDB.SetString(profileID.get(), "Path", descriptor.get());
1009
1010 // Should we flush now? It costs some startup time and we will fix it on
1011 // the next startup anyway. If something else causes a flush then it will
1012 // be fixed in the ini file then.
1013 }
1014
1015 rv = mProfileDB.GetString(profileID.get(), "Default", buffer);
1016 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && buffer.EqualsLiteral("1")) {
1017 mNormalDefault = currentProfile;
1018 }
1019
1020 // Is this the default profile for this install?
1021 if (mUseDedicatedProfile && !mDedicatedProfile &&
1022 installProfilePath.Equals(descriptor)) {
1023 // Found a profile for this install.
1024 mDedicatedProfile = currentProfile;
1025 }
1026
1027 if (name.EqualsLiteral(DEV_EDITION_NAME"dev-edition-default")) {
1028 mDevEditionDefault = currentProfile;
1029 } else {
1030 nonDevEditionProfiles++;
1031 autoSelectProfile = currentProfile;
1032 }
1033 }
1034
1035 // If there is only one non-dev-edition profile then mark it as the default.
1036 if (!mNormalDefault && nonDevEditionProfiles == 1) {
1037 SetNormalDefault(autoSelectProfile);
1038 }
1039
1040 if (!mUseDedicatedProfile) {
1041 if (mUseDevEditionProfile) {
1042 // When using the separate dev-edition profile not finding it means this
1043 // is a first run.
1044 mIsFirstRun = !mDevEditionDefault;
1045 } else {
1046 // If there are no normal profiles then this is a first run.
1047 mIsFirstRun = nonDevEditionProfiles == 0;
1048 }
1049 }
1050
1051 return NS_OK;
1052}
1053
1054NS_IMETHODIMPnsresult
1055nsToolkitProfileService::SetStartWithLastProfile(bool aValue) {
1056 if (mStartWithLast != aValue) {
1057 // Note: the skeleton ui (see PreXULSkeletonUI.cpp) depends on this
1058 // having this name and being under General. If that ever changes,
1059 // the skeleton UI will just need to be updated. If it changes frequently,
1060 // it's probably best we just mirror the value to the registry here.
1061 nsresult rv = mProfileDB.SetString("General", "StartWithLastProfile",
1062 aValue ? "1" : "0");
1063 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1063); return rv; } } while (false)
;
1064 mStartWithLast = aValue;
1065 }
1066 return NS_OK;
1067}
1068
1069NS_IMETHODIMPnsresult
1070nsToolkitProfileService::GetStartWithLastProfile(bool* aResult) {
1071 *aResult = mStartWithLast;
1072 return NS_OK;
1073}
1074
1075NS_IMETHODIMPnsresult
1076nsToolkitProfileService::GetProfiles(nsISimpleEnumerator** aResult) {
1077 *aResult = new ProfileEnumerator(mProfiles.getFirst());
1078
1079 NS_ADDREF(*aResult)(*aResult)->AddRef();
1080 return NS_OK;
1081}
1082
1083NS_IMETHODIMPnsresult
1084nsToolkitProfileService::ProfileEnumerator::HasMoreElements(bool* aResult) {
1085 *aResult = mCurrent ? true : false;
1086 return NS_OK;
1087}
1088
1089NS_IMETHODIMPnsresult
1090nsToolkitProfileService::ProfileEnumerator::GetNext(nsISupports** aResult) {
1091 if (!mCurrent) return NS_ERROR_FAILURE;
1092
1093 NS_ADDREF(*aResult = mCurrent)(*aResult = mCurrent)->AddRef();
1094
1095 mCurrent = mCurrent->getNext();
1096 return NS_OK;
1097}
1098
1099NS_IMETHODIMPnsresult
1100nsToolkitProfileService::GetCurrentProfile(nsIToolkitProfile** aResult) {
1101 NS_IF_ADDREF(*aResult = mCurrent)ns_if_addref(*aResult = mCurrent);
1102 return NS_OK;
1103}
1104
1105NS_IMETHODIMPnsresult
1106nsToolkitProfileService::GetDefaultProfile(nsIToolkitProfile** aResult) {
1107 if (mUseDedicatedProfile) {
1108 NS_IF_ADDREF(*aResult = mDedicatedProfile)ns_if_addref(*aResult = mDedicatedProfile);
1109 return NS_OK;
1110 }
1111
1112 if (mUseDevEditionProfile) {
1113 NS_IF_ADDREF(*aResult = mDevEditionDefault)ns_if_addref(*aResult = mDevEditionDefault);
1114 return NS_OK;
1115 }
1116
1117 NS_IF_ADDREF(*aResult = mNormalDefault)ns_if_addref(*aResult = mNormalDefault);
1118 return NS_OK;
1119}
1120
1121void nsToolkitProfileService::SetNormalDefault(nsIToolkitProfile* aProfile) {
1122 if (mNormalDefault == aProfile) {
1123 return;
1124 }
1125
1126 if (mNormalDefault) {
1127 nsToolkitProfile* profile =
1128 static_cast<nsToolkitProfile*>(mNormalDefault.get());
1129 mProfileDB.DeleteString(profile->mSection.get(), "Default");
1130 }
1131
1132 mNormalDefault = aProfile;
1133
1134 if (mNormalDefault) {
1135 nsToolkitProfile* profile =
1136 static_cast<nsToolkitProfile*>(mNormalDefault.get());
1137 mProfileDB.SetString(profile->mSection.get(), "Default", "1");
1138 }
1139}
1140
1141NS_IMETHODIMPnsresult
1142nsToolkitProfileService::SetDefaultProfile(nsIToolkitProfile* aProfile) {
1143 if (mUseDedicatedProfile) {
1144 if (mDedicatedProfile != aProfile) {
1145 if (!aProfile) {
1146 // Setting this to the empty string means no profile will be found on
1147 // startup but we'll recognise that this install has been used
1148 // previously.
1149 mProfileDB.SetString(mInstallSection.get(), "Default", "");
1150 } else {
1151 nsCString profilePath;
1152 nsresult rv = GetProfileDescriptor(aProfile, profilePath, nullptr);
1153 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1153); return rv; } } while (false)
;
1154
1155 mProfileDB.SetString(mInstallSection.get(), "Default",
1156 profilePath.get());
1157 }
1158 mDedicatedProfile = aProfile;
1159
1160 // Some kind of choice has happened here, lock this profile to this
1161 // install.
1162 mProfileDB.SetString(mInstallSection.get(), "Locked", "1");
1163 }
1164 return NS_OK;
1165 }
1166
1167 if (mUseDevEditionProfile && aProfile != mDevEditionDefault) {
1168 // The separate profile is hardcoded.
1169 return NS_ERROR_FAILURE;
1170 }
1171
1172 SetNormalDefault(aProfile);
1173
1174 return NS_OK;
1175}
1176
1177// Gets the profile root directory descriptor for storing in profiles.ini or
1178// installs.ini.
1179nsresult nsToolkitProfileService::GetProfileDescriptor(
1180 nsIToolkitProfile* aProfile, nsACString& aDescriptor, bool* aIsRelative) {
1181 nsCOMPtr<nsIFile> profileDir;
1182 nsresult rv = aProfile->GetRootDir(getter_AddRefs(profileDir));
1183 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1183); return rv; } } while (false)
;
1184
1185 // if the profile dir is relative to appdir...
1186 bool isRelative;
1187 rv = mAppData->Contains(profileDir, &isRelative);
1188
1189 nsCString profilePath;
1190 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && isRelative) {
1191 // we use a relative descriptor
1192 rv = profileDir->GetRelativeDescriptor(mAppData, profilePath);
1193 } else {
1194 // otherwise, a persistent descriptor
1195 rv = profileDir->GetPersistentDescriptor(profilePath);
1196 }
1197 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1197); return rv; } } while (false)
;
1198
1199 aDescriptor.Assign(profilePath);
1200 if (aIsRelative) {
1201 *aIsRelative = isRelative;
1202 }
1203
1204 return NS_OK;
1205}
1206
1207nsresult nsToolkitProfileService::CreateDefaultProfile(
1208 nsIToolkitProfile** aResult) {
1209 // Create a new default profile
1210 nsAutoCString name;
1211 if (mUseDevEditionProfile) {
1212 name.AssignLiteral(DEV_EDITION_NAME"dev-edition-default");
1213 } else if (mUseDedicatedProfile) {
1214 name.AppendPrintf("default-%s", mUpdateChannel.get());
1215 } else {
1216 name.AssignLiteral(DEFAULT_NAME"default");
1217 }
1218
1219 nsresult rv = CreateUniqueProfile(nullptr, name, aResult);
1220 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1220); return rv; } } while (false)
;
1221
1222 if (mUseDedicatedProfile) {
1223 SetDefaultProfile(mCurrent);
1224 } else if (mUseDevEditionProfile) {
1225 mDevEditionDefault = mCurrent;
1226 } else {
1227 SetNormalDefault(mCurrent);
1228 }
1229
1230 return NS_OK;
1231}
1232
1233/**
1234 * An implementation of SelectStartupProfile callable from JavaScript via XPCOM.
1235 * See nsIToolkitProfileService.idl.
1236 */
1237NS_IMETHODIMPnsresult
1238nsToolkitProfileService::SelectStartupProfile(
1239 const nsTArray<nsCString>& aArgv, bool aIsResetting,
1240 const nsACString& aUpdateChannel, const nsACString& aLegacyInstallHash,
1241 nsIFile** aRootDir, nsIFile** aLocalDir, nsIToolkitProfile** aProfile,
1242 bool* aDidCreate) {
1243 int argc = aArgv.Length();
1244 // Our command line handling expects argv to be null-terminated so construct
1245 // an appropriate array.
1246 auto argv = MakeUnique<char*[]>(argc + 1);
1247 // Also, our command line handling removes things from the array without
1248 // freeing them so keep track of what we've created separately.
1249 auto allocated = MakeUnique<UniqueFreePtr<char>[]>(argc);
1250
1251 for (int i = 0; i < argc; i++) {
1252 allocated[i].reset(ToNewCString(aArgv[i]));
1253 argv[i] = allocated[i].get();
1254 }
1255 argv[argc] = nullptr;
1256
1257 mUpdateChannel = aUpdateChannel;
1258 if (!aLegacyInstallHash.IsEmpty()) {
1259 mLegacyInstallSection.Assign(aLegacyInstallHash);
1260 mLegacyInstallSection.Insert(INSTALL_PREFIX"Install", 0);
1261 }
1262
1263 bool wasDefault;
1264 nsresult rv =
1265 SelectStartupProfile(&argc, argv.get(), aIsResetting, aRootDir, aLocalDir,
1266 aProfile, aDidCreate, &wasDefault);
1267
1268 // Since we were called outside of the normal startup path complete any
1269 // startup tasks.
1270 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1271 CompleteStartup();
1272 }
1273
1274 return rv;
1275}
1276
1277static void SaltProfileName(nsACString& aName);
1278
1279/**
1280 * Selects or creates a profile to use based on the profiles database, any
1281 * environment variables and any command line arguments. Will not create
1282 * a profile if aIsResetting is true. The profile is selected based on this
1283 * order of preference:
1284 * * Environment variables (set when restarting the application).
1285 * * --profile command line argument.
1286 * * --createprofile command line argument (this also causes the app to exit).
1287 * * -p command line argument.
1288 * * A new profile created if this is the first run of the application.
1289 * * The default profile.
1290 * aRootDir and aLocalDir are set to the data and local directories for the
1291 * profile data. If a profile from the database was selected it will be
1292 * returned in aProfile.
1293 * aDidCreate will be set to true if a new profile was created.
1294 * This function should be called once at startup and will fail if called again.
1295 * aArgv should be an array of aArgc + 1 strings, the last element being null.
1296 * Both aArgv and aArgc will be mutated.
1297 */
1298nsresult nsToolkitProfileService::SelectStartupProfile(
1299 int* aArgc, char* aArgv[], bool aIsResetting, nsIFile** aRootDir,
1300 nsIFile** aLocalDir, nsIToolkitProfile** aProfile, bool* aDidCreate,
1301 bool* aWasDefaultSelection) {
1302 if (mStartupProfileSelected) {
1303 return NS_ERROR_ALREADY_INITIALIZED;
1304 }
1305
1306 mStartupProfileSelected = true;
1307 *aDidCreate = false;
1308 *aWasDefaultSelection = false;
1309
1310 nsresult rv;
1311 const char* arg;
1312
1313 // Use the profile specified in the environment variables (generally from an
1314 // app initiated restart).
1315 nsCOMPtr<nsIFile> lf = GetFileFromEnv("XRE_PROFILE_PATH");
1316 if (lf) {
1317 nsCOMPtr<nsIFile> localDir = GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
1318 if (!localDir) {
1319 localDir = lf;
1320 }
1321
1322 // Clear out flags that we handled (or should have handled!) last startup.
1323 const char* dummy;
1324 CheckArg(*aArgc, aArgv, "p", &dummy);
1325 CheckArg(*aArgc, aArgv, "profile", &dummy);
1326 CheckArg(*aArgc, aArgv, "profilemanager");
1327
1328 nsCOMPtr<nsIToolkitProfile> profile;
1329 GetProfileByDir(lf, localDir, getter_AddRefs(profile));
1330
1331 if (profile && mIsFirstRun && mUseDedicatedProfile) {
1332 if (profile ==
1333 (mUseDevEditionProfile ? mDevEditionDefault : mNormalDefault)) {
1334 // This is the first run of a dedicated profile build where the selected
1335 // profile is the previous default so we should either make it the
1336 // default profile for this install or push the user to a new profile.
1337
1338 bool result;
1339 rv = MaybeMakeDefaultDedicatedProfile(profile, &result);
1340 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1340); return rv; } } while (false)
;
1341 if (result) {
1342 mStartupReason = u"restart-claimed-default"_ns;
1343
1344 mCurrent = profile;
1345 } else {
1346 rv = CreateDefaultProfile(getter_AddRefs(mCurrent));
1347 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1348 *aProfile = nullptr;
1349 return rv;
1350 }
1351
1352 rv = Flush();
1353 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1353); return rv; } } while (false)
;
1354
1355 mStartupReason = u"restart-skipped-default"_ns;
1356 *aDidCreate = true;
1357 }
1358
1359 NS_IF_ADDREF(*aProfile = mCurrent)ns_if_addref(*aProfile = mCurrent);
1360 mCurrent->GetRootDir(aRootDir);
1361 mCurrent->GetLocalDir(aLocalDir);
1362
1363 return NS_OK;
1364 }
1365 }
1366
1367 if (EnvHasValue("XRE_RESTARTED_BY_PROFILE_MANAGER")) {
1368 mStartupReason = u"profile-manager"_ns;
1369 } else if (aIsResetting) {
1370 mStartupReason = u"profile-reset"_ns;
1371 } else {
1372 mStartupReason = u"restart"_ns;
1373 }
1374
1375 mCurrent = profile;
1376 lf.forget(aRootDir);
1377 localDir.forget(aLocalDir);
1378 NS_IF_ADDREF(*aProfile = profile)ns_if_addref(*aProfile = profile);
1379 return NS_OK;
1380 }
1381
1382 // Check the -profile command line argument. It accepts a single argument that
1383 // gives the path to use for the profile.
1384 ArgResult ar = CheckArg(*aArgc, aArgv, "profile", &arg);
1385 if (ar == ARG_BAD) {
1386 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Error: argument --profile requires a path\n");
1387 return NS_ERROR_FAILURE;
1388 }
1389 if (ar) {
1390 nsCOMPtr<nsIFile> lf;
1391 rv = XRE_GetFileFromPath(arg, getter_AddRefs(lf));
1392 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1392); return rv; } } while (false)
;
1393
1394 // Make sure that the profile path exists and it's a directory.
1395 bool exists;
1396 rv = lf->Exists(&exists);
1397 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1397); return rv; } } while (false)
;
1398 if (!exists) {
1399 rv = lf->Create(nsIFile::DIRECTORY_TYPE, 0700);
1400 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1400); return rv; } } while (false)
;
1401 } else {
1402 bool isDir;
1403 rv = lf->IsDirectory(&isDir);
1404 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1404); return rv; } } while (false)
;
1405 if (!isDir) {
1406 PR_fprintf(
1407 PR_STDERRPR_GetSpecialFD(PR_StandardError),
1408 "Error: argument --profile requires a path to a directory\n");
1409 return NS_ERROR_FAILURE;
1410 }
1411 }
1412
1413 mStartupReason = u"argument-profile"_ns;
1414
1415 GetProfileByDir(lf, nullptr, getter_AddRefs(mCurrent));
1416 NS_ADDREF(*aRootDir = lf)(*aRootDir = lf)->AddRef();
1417 // If the root dir matched a profile then use its local dir, otherwise use
1418 // the root dir as the local dir.
1419 if (mCurrent) {
1420 mCurrent->GetLocalDir(aLocalDir);
1421 } else {
1422 lf.forget(aLocalDir);
1423 }
1424
1425 NS_IF_ADDREF(*aProfile = mCurrent)ns_if_addref(*aProfile = mCurrent);
1426 return NS_OK;
1427 }
1428
1429 // Check the -createprofile command line argument. It accepts a single
1430 // argument that is either the name for the new profile or the name followed
1431 // by the path to use.
1432 ar = CheckArg(*aArgc, aArgv, "createprofile", &arg, CheckArgFlag::RemoveArg);
1433 if (ar == ARG_BAD) {
1434 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
1435 "Error: argument --createprofile requires a profile name\n");
1436 return NS_ERROR_FAILURE;
1437 }
1438 if (ar) {
1439 const char* delim = strchr(arg, ' ');
1440 nsCOMPtr<nsIToolkitProfile> profile;
1441 if (delim) {
1442 nsCOMPtr<nsIFile> lf;
1443 rv = NS_NewNativeLocalFile(nsDependentCString(delim + 1), true,
1444 getter_AddRefs(lf));
1445 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1446 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Error: profile path not valid.\n");
1447 return rv;
1448 }
1449
1450 // As with --profile, assume that the given path will be used for the
1451 // main profile directory.
1452 rv = CreateProfile(lf, nsDependentCSubstring(arg, delim),
1453 getter_AddRefs(profile));
1454 } else {
1455 rv = CreateProfile(nullptr, nsDependentCString(arg),
1456 getter_AddRefs(profile));
1457 }
1458 // Some pathological arguments can make it this far
1459 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_FAILED(Flush())((bool)(__builtin_expect(!!(NS_FAILED_impl(Flush())), 0)))) {
1460 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Error creating profile.\n");
1461 }
1462 return NS_ERROR_ABORT;
1463 }
1464
1465 // Check the -p command line argument. It either accepts a profile name and
1466 // uses that named profile or without a name it opens the profile manager.
1467 ar = CheckArg(*aArgc, aArgv, "p", &arg);
1468 if (ar == ARG_BAD) {
1469 return NS_ERROR_SHOW_PROFILE_MANAGER;
1470 }
1471 if (ar) {
1472 rv = GetProfileByName(nsDependentCString(arg), getter_AddRefs(mCurrent));
1473 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1474 mStartupReason = u"argument-p"_ns;
1475
1476 mCurrent->GetRootDir(aRootDir);
1477 mCurrent->GetLocalDir(aLocalDir);
1478
1479 NS_ADDREF(*aProfile = mCurrent)(*aProfile = mCurrent)->AddRef();
1480 return NS_OK;
1481 }
1482
1483 return NS_ERROR_SHOW_PROFILE_MANAGER;
1484 }
1485
1486 ar = CheckArg(*aArgc, aArgv, "profilemanager");
1487 if (ar == ARG_FOUND) {
1488 return NS_ERROR_SHOW_PROFILE_MANAGER;
1489 }
1490
1491#ifdef MOZ_BACKGROUNDTASKS1
1492 if (BackgroundTasks::IsBackgroundTaskMode()) {
1493 // There are two cases:
1494 // 1. ephemeral profile: create a new one in temporary directory.
1495 // 2. non-ephemeral (persistent) profile:
1496 // a. if no salted profile is known, create a new one in
1497 // background task-specific directory.
1498 // b. if salted profile is know, use salted path.
1499 nsString installHash;
1500 rv = gDirServiceProvider->GetInstallHash(installHash);
1501 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1501); return rv; } } while (false)
;
1502
1503 nsCString profilePrefix(BackgroundTasks::GetProfilePrefix(
1504 NS_LossyConvertUTF16toASCII(installHash)));
1505
1506 nsCString taskName(BackgroundTasks::GetBackgroundTasks().ref());
1507
1508 nsCOMPtr<nsIFile> file;
1509
1510 if (BackgroundTasks::IsEphemeralProfileTaskName(taskName)) {
1511 // Background task mode does not enable legacy telemetry, so this is for
1512 // completeness and testing only.
1513 mStartupReason = u"backgroundtask-ephemeral"_ns;
1514
1515 nsCOMPtr<nsIFile> rootDir;
1516 rv = GetSpecialSystemDirectory(OS_TemporaryDirectory,
1517 getter_AddRefs(rootDir));
1518 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1518); return rv; } } while (false)
;
1519
1520 nsresult rv = BackgroundTasks::CreateEphemeralProfileDirectory(
1521 rootDir, profilePrefix, getter_AddRefs(file));
1522 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1522)
) {
1523 // In background task mode, NS_ERROR_UNEXPECTED is handled specially to
1524 // exit with a non-zero exit code.
1525 return NS_ERROR_UNEXPECTED;
1526 }
1527 *aDidCreate = true;
1528 } else {
1529 // Background task mode does not enable legacy telemetry, so this is for
1530 // completeness and testing only.
1531 mStartupReason = u"backgroundtask-not-ephemeral"_ns;
1532
1533 // A non-ephemeral profile is required.
1534 nsCOMPtr<nsIFile> rootDir;
1535 nsresult rv = gDirServiceProvider->GetBackgroundTasksProfilesRootDir(
1536 getter_AddRefs(rootDir));
1537 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1537); return rv; } } while (false)
;
1538
1539 nsAutoCString buffer;
1540 rv = mProfileDB.GetString("BackgroundTasksProfiles", profilePrefix.get(),
1541 buffer);
1542 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1543 // We have a record of one! Use it.
1544 rv = rootDir->Clone(getter_AddRefs(file));
1545 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1545); return rv; } } while (false)
;
1546
1547 rv = file->AppendNative(buffer);
1548 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1548); return rv; } } while (false)
;
1549 } else {
1550 nsCString saltedProfilePrefix = profilePrefix;
1551 SaltProfileName(saltedProfilePrefix);
1552
1553 nsresult rv = BackgroundTasks::CreateNonEphemeralProfileDirectory(
1554 rootDir, saltedProfilePrefix, getter_AddRefs(file));
1555 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1555)
) {
1556 // In background task mode, NS_ERROR_UNEXPECTED is handled specially
1557 // to exit with a non-zero exit code.
1558 return NS_ERROR_UNEXPECTED;
1559 }
1560 *aDidCreate = true;
1561
1562 // Keep a record of the salted name. It's okay if this doesn't succeed:
1563 // not great, but it's better for tasks (particularly,
1564 // `backgroundupdate`) to run and not persist state correctly than to
1565 // not run at all.
1566 rv =
1567 mProfileDB.SetString("BackgroundTasksProfiles", profilePrefix.get(),
1568 saltedProfilePrefix.get());
1569 Unused << NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1569)
;
1570
1571 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1572 rv = Flush();
1573 Unused << NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1573)
;
1574 }
1575 }
1576 }
1577
1578 nsCOMPtr<nsIFile> localDir = file;
1579 file.forget(aRootDir);
1580 localDir.forget(aLocalDir);
1581
1582 // Background tasks never use profiles known to the profile service.
1583 *aProfile = nullptr;
1584
1585 return NS_OK;
1586 }
1587#endif
1588
1589 if (mIsFirstRun && mUseDedicatedProfile &&
1590 !mInstallSection.Equals(mLegacyInstallSection)) {
1591 // The default profile could be assigned to a hash generated from an
1592 // incorrectly cased version of the installation directory (see bug
1593 // 1555319). Ideally we'd do all this while loading profiles.ini but we
1594 // can't override the legacy section value before that for tests.
1595 nsCString defaultDescriptor;
1596 rv = mProfileDB.GetString(mLegacyInstallSection.get(), "Default",
1597 defaultDescriptor);
1598
1599 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1600 // There is a default here, need to see if it matches any profiles.
1601 bool isRelative;
1602 nsCString descriptor;
1603
1604 for (RefPtr<nsToolkitProfile> profile : mProfiles) {
1605 GetProfileDescriptor(profile, descriptor, &isRelative);
1606
1607 if (descriptor.Equals(defaultDescriptor)) {
1608 // Found the default profile. Copy the install section over to
1609 // the correct location. We leave the old info in place for older
1610 // versions of Firefox to use.
1611 nsTArray<UniquePtr<KeyValue>> strings =
1612 GetSectionStrings(&mProfileDB, mLegacyInstallSection.get());
1613 for (const auto& kv : strings) {
1614 mProfileDB.SetString(mInstallSection.get(), kv->key.get(),
1615 kv->value.get());
1616 }
1617
1618 // Flush now. This causes a small blip in startup but it should be
1619 // one time only whereas not flushing means we have to do this search
1620 // on every startup.
1621 Flush();
1622
1623 // Now start up with the found profile.
1624 mDedicatedProfile = profile;
1625 mIsFirstRun = false;
1626 break;
1627 }
1628 }
1629 }
1630 }
1631
1632 // If this is a first run then create a new profile.
1633 if (mIsFirstRun) {
1634 // If we're configured to always show the profile manager then don't create
1635 // a new profile to use.
1636 if (!mStartWithLast) {
1637 return NS_ERROR_SHOW_PROFILE_MANAGER;
1638 }
1639
1640 bool skippedDefaultProfile = false;
1641
1642 if (mUseDedicatedProfile) {
1643 // This is the first run of a dedicated profile install. We have to decide
1644 // whether to use the default profile used by non-dedicated-profile
1645 // installs or to create a new profile.
1646
1647 // Find what would have been the default profile for old installs.
1648 nsCOMPtr<nsIToolkitProfile> profile = mNormalDefault;
1649 if (mUseDevEditionProfile) {
1650 profile = mDevEditionDefault;
1651 }
1652
1653 if (profile) {
1654 nsCOMPtr<nsIFile> rootDir;
1655 profile->GetRootDir(getter_AddRefs(rootDir));
1656
1657 nsCOMPtr<nsIFile> compat;
1658 rootDir->Clone(getter_AddRefs(compat));
1659 compat->Append(COMPAT_FILEu"compatibility.ini"_ns);
1660
1661 bool exists;
1662 rv = compat->Exists(&exists);
1663 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1663); return rv; } } while (false)
;
1664
1665 // If the file is missing then either this is an empty profile (likely
1666 // generated by bug 1518591) or it is from an ancient version. We'll opt
1667 // to leave it for older versions in this case.
1668 if (exists) {
1669 bool result;
1670 rv = MaybeMakeDefaultDedicatedProfile(profile, &result);
1671 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1671); return rv; } } while (false)
;
1672 if (result) {
1673 mStartupReason = u"firstrun-claimed-default"_ns;
1674
1675 mCurrent = profile;
1676 rootDir.forget(aRootDir);
1677 profile->GetLocalDir(aLocalDir);
1678 profile.forget(aProfile);
1679 return NS_OK;
1680 }
1681
1682 // We're going to create a new profile for this install even though
1683 // another default exists.
1684 skippedDefaultProfile = true;
1685 }
1686 }
1687 }
1688
1689 rv = CreateDefaultProfile(getter_AddRefs(mCurrent));
1690 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1691#ifdef MOZ_CREATE_LEGACY_PROFILE1
1692 // If there is only one profile and it isn't meant to be the profile that
1693 // older versions of Firefox use then we must create a default profile
1694 // for older versions of Firefox to avoid the existing profile being
1695 // auto-selected.
1696 if ((mUseDedicatedProfile || mUseDevEditionProfile) &&
1697 mProfiles.getFirst() == mProfiles.getLast()) {
1698 nsCOMPtr<nsIToolkitProfile> newProfile;
1699 CreateProfile(nullptr, nsLiteralCString(DEFAULT_NAME"default"),
1700 getter_AddRefs(newProfile));
1701 SetNormalDefault(newProfile);
1702 }
1703#endif
1704
1705 rv = Flush();
1706 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1706); return rv; } } while (false)
;
1707
1708 if (skippedDefaultProfile) {
1709 mStartupReason = u"firstrun-skipped-default"_ns;
1710 } else {
1711 mStartupReason = u"firstrun-created-default"_ns;
1712 }
1713
1714 // Use the new profile.
1715 mCurrent->GetRootDir(aRootDir);
1716 mCurrent->GetLocalDir(aLocalDir);
1717 NS_ADDREF(*aProfile = mCurrent)(*aProfile = mCurrent)->AddRef();
1718
1719 *aDidCreate = true;
1720 return NS_OK;
1721 }
1722 }
1723
1724 GetDefaultProfile(getter_AddRefs(mCurrent));
1725
1726 // None of the profiles was marked as default (generally only happens if the
1727 // user modifies profiles.ini manually). Let the user choose.
1728 if (!mCurrent) {
1729 return NS_ERROR_SHOW_PROFILE_MANAGER;
1730 }
1731
1732 // Let the caller know that the profile was selected by default.
1733 *aWasDefaultSelection = true;
1734 mStartupReason = u"default"_ns;
1735
1736 // Use the selected profile.
1737 mCurrent->GetRootDir(aRootDir);
1738 mCurrent->GetLocalDir(aLocalDir);
1739 NS_ADDREF(*aProfile = mCurrent)(*aProfile = mCurrent)->AddRef();
1740
1741 return NS_OK;
1742}
1743
1744/**
1745 * Creates a new profile for reset and mark it as the current profile.
1746 */
1747nsresult nsToolkitProfileService::CreateResetProfile(
1748 nsIToolkitProfile** aNewProfile) {
1749 nsAutoCString oldProfileName;
1750 mCurrent->GetName(oldProfileName);
1751
1752 nsCOMPtr<nsIToolkitProfile> newProfile;
1753 // Make the new profile name the old profile (or "default-") + the time in
1754 // seconds since epoch for uniqueness.
1755 nsAutoCString newProfileName;
1756 if (!oldProfileName.IsEmpty()) {
1757 newProfileName.Assign(oldProfileName);
1758 newProfileName.Append("-");
1759 } else {
1760 newProfileName.AssignLiteral("default-");
1761 }
1762 newProfileName.AppendPrintf("%" PRId64"l" "d", PR_Now() / 1000);
1763 nsresult rv = CreateProfile(nullptr, // choose a default dir for us
1764 newProfileName, getter_AddRefs(newProfile));
1765 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1766
1767 mCurrent = newProfile;
1768 newProfile.forget(aNewProfile);
1769
1770 // Don't flush the changes yet. That will happen once the migration
1771 // successfully completes.
1772 return NS_OK;
1773}
1774
1775/**
1776 * This is responsible for deleting the old profile, copying its name to the
1777 * current profile and if the old profile was default making the new profile
1778 * default as well.
1779 */
1780nsresult nsToolkitProfileService::ApplyResetProfile(
1781 nsIToolkitProfile* aOldProfile) {
1782 // If the old profile would have been the default for old installs then mark
1783 // the new profile as such.
1784 if (mNormalDefault == aOldProfile) {
1785 SetNormalDefault(mCurrent);
1786 }
1787
1788 if (mUseDedicatedProfile && mDedicatedProfile == aOldProfile) {
1789 bool wasLocked = false;
1790 nsCString val;
1791 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mProfileDB.GetString
(mInstallSection.get(), "Locked", val))), 1)))
1792 mProfileDB.GetString(mInstallSection.get(), "Locked", val))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mProfileDB.GetString
(mInstallSection.get(), "Locked", val))), 1)))
) {
1793 wasLocked = val.Equals("1");
1794 }
1795
1796 SetDefaultProfile(mCurrent);
1797
1798 // Make the locked state match if necessary.
1799 if (!wasLocked) {
1800 mProfileDB.DeleteString(mInstallSection.get(), "Locked");
1801 }
1802 }
1803
1804 nsCString name;
1805 nsresult rv = aOldProfile->GetName(name);
1806 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1806); return rv; } } while (false)
;
1807
1808 // Don't remove the old profile's files until after we've successfully flushed
1809 // the profile changes to disk.
1810 rv = aOldProfile->Remove(false);
1811 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1811); return rv; } } while (false)
;
1812
1813 // Switching the name will make this the default for dev-edition if
1814 // appropriate.
1815 rv = mCurrent->SetName(name);
1816 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1816); return rv; } } while (false)
;
1817
1818 rv = Flush();
1819 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1819); return rv; } } while (false)
;
1820
1821 // Now that the profile changes are flushed, try to remove the old profile's
1822 // files. If we fail the worst that will happen is that an orphan directory is
1823 // left. Let this run in the background while we start up.
1824 RemoveProfileFiles(aOldProfile, true);
1825
1826 return NS_OK;
1827}
1828
1829NS_IMETHODIMPnsresult
1830nsToolkitProfileService::GetProfileByName(const nsACString& aName,
1831 nsIToolkitProfile** aResult) {
1832 for (RefPtr<nsToolkitProfile> profile : mProfiles) {
1833 if (profile->mName.Equals(aName)) {
1834 NS_ADDREF(*aResult = profile)(*aResult = profile)->AddRef();
1835 return NS_OK;
1836 }
1837 }
1838
1839 return NS_ERROR_FAILURE;
1840}
1841
1842/**
1843 * Finds a profile from the database that uses the given root and local
1844 * directories.
1845 */
1846void nsToolkitProfileService::GetProfileByDir(nsIFile* aRootDir,
1847 nsIFile* aLocalDir,
1848 nsIToolkitProfile** aResult) {
1849 for (RefPtr<nsToolkitProfile> profile : mProfiles) {
1850 bool equal;
1851 nsresult rv = profile->mRootDir->Equals(aRootDir, &equal);
1852 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && equal) {
1853 if (!aLocalDir) {
1854 // If no local directory was given then we will just use the normal
1855 // local directory for the profile.
1856 profile.forget(aResult);
1857 return;
1858 }
1859
1860 rv = profile->mLocalDir->Equals(aLocalDir, &equal);
1861 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && equal) {
1862 profile.forget(aResult);
1863 return;
1864 }
1865 }
1866 }
1867}
1868
1869nsresult NS_LockProfilePath(nsIFile* aPath, nsIFile* aTempPath,
1870 nsIProfileUnlocker** aUnlocker,
1871 nsIProfileLock** aResult) {
1872 RefPtr<nsToolkitProfileLock> lock = new nsToolkitProfileLock();
1873
1874 nsresult rv = lock->Init(aPath, aTempPath, aUnlocker);
1875 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1876
1877 lock.forget(aResult);
1878 return NS_OK;
1879}
1880
1881static void SaltProfileName(nsACString& aName) {
1882 char salt[9];
1883 NS_MakeRandomString(salt, 8);
1884 salt[8] = '.';
1885
1886 aName.Insert(salt, 0, 9);
1887}
1888
1889NS_IMETHODIMPnsresult
1890nsToolkitProfileService::CreateUniqueProfile(nsIFile* aRootDir,
1891 const nsACString& aNamePrefix,
1892 nsIToolkitProfile** aResult) {
1893 nsCOMPtr<nsIToolkitProfile> profile;
1894 nsresult rv = GetProfileByName(aNamePrefix, getter_AddRefs(profile));
1895 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1896 return CreateProfile(aRootDir, aNamePrefix, aResult);
1897 }
1898
1899 uint32_t suffix = 1;
1900 while (true) {
1901 nsPrintfCString name("%s-%d", PromiseFlatCStringTPromiseFlatString<char>(aNamePrefix).get(),
1902 suffix);
1903 rv = GetProfileByName(name, getter_AddRefs(profile));
1904 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1905 return CreateProfile(aRootDir, name, aResult);
1906 }
1907 suffix++;
1908 }
1909}
1910
1911NS_IMETHODIMPnsresult
1912nsToolkitProfileService::CreateProfile(nsIFile* aRootDir,
1913 const nsACString& aName,
1914 nsIToolkitProfile** aResult) {
1915 nsresult rv = GetProfileByName(aName, aResult);
1916 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1917 return rv;
1918 }
1919
1920 nsCOMPtr<nsIFile> rootDir(aRootDir);
1921
1922 nsAutoCString dirName;
1923 if (!rootDir) {
1924 rv = gDirServiceProvider->GetUserProfilesRootDir(getter_AddRefs(rootDir));
1925 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1925); return rv; } } while (false)
;
1926
1927 dirName = aName;
1928 SaltProfileName(dirName);
1929
1930 if (NS_IsNativeUTF8()) {
1931 rootDir->AppendNative(dirName);
1932 } else {
1933 rootDir->Append(NS_ConvertUTF8toUTF16(dirName));
1934 }
1935 }
1936
1937 nsCOMPtr<nsIFile> localDir;
1938
1939 bool isRelative;
1940 rv = mAppData->Contains(rootDir, &isRelative);
1941 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && isRelative) {
1942 nsAutoCString path;
1943 rv = rootDir->GetRelativeDescriptor(mAppData, path);
1944 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1944); return rv; } } while (false)
;
1945
1946 rv = NS_NewNativeLocalFile(""_ns, true, getter_AddRefs(localDir));
1947 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1947); return rv; } } while (false)
;
1948
1949 rv = localDir->SetRelativeDescriptor(mTempData, path);
Value stored to 'rv' is never read
1950 } else {
1951 localDir = rootDir;
1952 }
1953
1954 bool exists;
1955 rv = rootDir->Exists(&exists);
1956 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1956); return rv; } } while (false)
;
1957
1958 if (exists) {
1959 rv = rootDir->IsDirectory(&exists);
1960 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1960); return rv; } } while (false)
;
1961
1962 if (!exists) return NS_ERROR_FILE_NOT_DIRECTORY;
1963 } else {
1964 nsCOMPtr<nsIFile> profileDirParent;
1965 nsAutoString profileDirName;
1966
1967 rv = rootDir->GetParent(getter_AddRefs(profileDirParent));
1968 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1968); return rv; } } while (false)
;
1969
1970 rv = rootDir->GetLeafName(profileDirName);
1971 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1971); return rv; } } while (false)
;
1972
1973 // let's ensure that the profile directory exists.
1974 rv = rootDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
1975 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1975); return rv; } } while (false)
;
1976 rv = rootDir->SetPermissions(0700);
1977#ifndef ANDROID
1978 // If the profile is on the sdcard, this will fail but its non-fatal
1979 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1979); return rv; } } while (false)
;
1980#endif
1981 }
1982
1983 rv = localDir->Exists(&exists);
1984 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1984); return rv; } } while (false)
;
1985
1986 if (!exists) {
1987 rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
1988 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1988); return rv; } } while (false)
;
1989 }
1990
1991 // We created a new profile dir. Let's store a creation timestamp.
1992 // Note that this code path does not apply if the profile dir was
1993 // created prior to launching.
1994 rv = CreateTimesInternal(rootDir);
1995 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 1995); return rv; } } while (false)
;
1996
1997 nsCOMPtr<nsIToolkitProfile> profile =
1998 new nsToolkitProfile(aName, rootDir, localDir, false);
1999
2000 if (aName.Equals(DEV_EDITION_NAME"dev-edition-default")) {
2001 mDevEditionDefault = profile;
2002 }
2003
2004 profile.forget(aResult);
2005 return NS_OK;
2006}
2007
2008/**
2009 * Snaps (https://snapcraft.io/) use a different installation directory for
2010 * every version of an application. Since dedicated profiles uses the
2011 * installation directory to determine which profile to use this would lead
2012 * snap users getting a new profile on every application update.
2013 *
2014 * However the only way to have multiple installation of a snap is to install
2015 * a new snap instance. Different snap instances have different user data
2016 * directories and so already will not share profiles, in fact one instance
2017 * will not even be able to see the other instance's profiles since
2018 * profiles.ini will be stored in different places.
2019 *
2020 * So we can just disable dedicated profile support in this case and revert
2021 * back to the old method of just having a single default profile and still
2022 * get essentially the same benefits as dedicated profiles provides.
2023 */
2024bool nsToolkitProfileService::IsSnapEnvironment() {
2025#ifdef MOZ_WIDGET_GTK1
2026 return widget::IsRunningUnderSnap();
2027#else
2028 return false;
2029#endif
2030}
2031
2032/**
2033 * In some situations dedicated profile support does not work well. This
2034 * includes a handful of linux distributions which always install different
2035 * application versions to different locations, some application sandboxing
2036 * systems as well as enterprise deployments. This environment variable provides
2037 * a way to opt out of dedicated profiles for these cases.
2038 *
2039 * For Windows, we provide a policy to accomplish the same thing.
2040 */
2041bool nsToolkitProfileService::UseLegacyProfiles() {
2042 bool legacyProfiles = !!PR_GetEnv("MOZ_LEGACY_PROFILES");
2043#ifdef XP_WIN
2044 legacyProfiles |= PolicyCheckBoolean(L"LegacyProfiles");
2045#endif
2046 return legacyProfiles;
2047}
2048
2049struct FindInstallsClosure {
2050 nsINIParsernsINIParser_internal* installData;
2051 nsTArray<nsCString>* installs;
2052};
2053
2054static bool FindInstalls(const char* aSection, void* aClosure) {
2055 FindInstallsClosure* closure = static_cast<FindInstallsClosure*>(aClosure);
2056
2057 // Check if the section starts with "Install"
2058 if (strncmp(aSection, INSTALL_PREFIX"Install", INSTALL_PREFIX_LENGTH7) != 0) {
2059 return true;
2060 }
2061
2062 nsCString install(aSection);
2063 closure->installs->AppendElement(install);
2064
2065 return true;
2066}
2067
2068nsTArray<nsCString> nsToolkitProfileService::GetKnownInstalls() {
2069 nsTArray<nsCString> result;
2070 FindInstallsClosure closure = {&mProfileDB, &result};
2071
2072 mProfileDB.GetSections(&FindInstalls, &closure);
2073
2074 return result;
2075}
2076
2077nsresult nsToolkitProfileService::CreateTimesInternal(nsIFile* aProfileDir) {
2078 nsresult rv = NS_ERROR_FAILURE;
2079 nsCOMPtr<nsIFile> creationLog;
2080 rv = aProfileDir->Clone(getter_AddRefs(creationLog));
2081 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 2081); return rv; } } while (false)
;
2082
2083 rv = creationLog->AppendNative("times.json"_ns);
2084 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 2084); return rv; } } while (false)
;
2085
2086 bool exists = false;
2087 creationLog->Exists(&exists);
2088 if (exists) {
2089 return NS_OK;
2090 }
2091
2092 rv = creationLog->Create(nsIFile::NORMAL_FILE_TYPE, 0700);
2093 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 2093); return rv; } } while (false)
;
2094
2095 // We don't care about microsecond resolution.
2096 int64_t msec = PR_Now() / PR_USEC_PER_MSEC1000L;
2097
2098 // Write it out.
2099 PRFileDesc* writeFile;
2100 rv = creationLog->OpenNSPRFileDesc(PR_WRONLY0x02, 0700, &writeFile);
2101 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 2101); return rv; } } while (false)
;
2102
2103 PR_fprintf(writeFile, "{\n\"created\": %lld,\n\"firstUse\": null\n}\n", msec);
2104 PR_Close(writeFile);
2105 return NS_OK;
2106}
2107
2108NS_IMETHODIMPnsresult
2109nsToolkitProfileService::GetProfileCount(uint32_t* aResult) {
2110 *aResult = 0;
2111 for (nsToolkitProfile* profile : mProfiles) {
2112 Unused << profile;
2113 (*aResult)++;
2114 }
2115
2116 return NS_OK;
2117}
2118
2119NS_IMETHODIMPnsresult
2120nsToolkitProfileService::Flush() {
2121 if (GetIsListOutdated()) {
2122 return NS_ERROR_DATABASE_CHANGED;
2123 }
2124
2125 nsresult rv;
2126
2127 // If we aren't using dedicated profiles then nothing about the list of
2128 // installs can have changed, so no need to update the backup.
2129 if (mUseDedicatedProfile) {
2130 // Export the installs to the backup.
2131 nsTArray<nsCString> installs = GetKnownInstalls();
2132
2133 if (!installs.IsEmpty()) {
2134 nsCString data;
2135 nsCString buffer;
2136
2137 for (uint32_t i = 0; i < installs.Length(); i++) {
2138 nsTArray<UniquePtr<KeyValue>> strings =
2139 GetSectionStrings(&mProfileDB, installs[i].get());
2140 if (strings.IsEmpty()) {
2141 continue;
2142 }
2143
2144 // Strip "Install" from the start.
2145 const nsDependentCSubstring& install =
2146 Substring(installs[i], INSTALL_PREFIX_LENGTH7);
2147 data.AppendPrintf("[%s]\n", PromiseFlatCStringTPromiseFlatString<char>(install).get());
2148
2149 for (uint32_t j = 0; j < strings.Length(); j++) {
2150 data.AppendPrintf("%s=%s\n", strings[j]->key.get(),
2151 strings[j]->value.get());
2152 }
2153
2154 data.Append("\n");
2155 }
2156
2157 FILE* writeFile;
2158 rv = mInstallDBFile->OpenANSIFileDesc("w", &writeFile);
2159 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 2159); return rv; } } while (false)
;
2160
2161 uint32_t length = data.Length();
2162 if (fwrite(data.get(), sizeof(char), length, writeFile) != length) {
2163 fclose(writeFile);
2164 return NS_ERROR_UNEXPECTED;
2165 }
2166
2167 fclose(writeFile);
2168 } else {
2169 rv = mInstallDBFile->Remove(false);
2170 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv != NS_ERROR_FILE_NOT_FOUND) {
2171 return rv;
2172 }
2173 }
2174 }
2175
2176 rv = mProfileDB.WriteToFile(mProfileDBFile);
2177 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 2177); return rv; } } while (false)
;
2178
2179 rv = UpdateFileStats(mProfileDBFile, &mProfileDBExists,
2180 &mProfileDBModifiedTime, &mProfileDBFileSize);
2181 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 2181); return rv; } } while (false)
;
2182
2183 return NS_OK;
2184}
2185
2186already_AddRefed<nsToolkitProfileService> NS_GetToolkitProfileService() {
2187 if (!nsToolkitProfileService::gService) {
2188 nsToolkitProfileService::gService = new nsToolkitProfileService();
2189 nsresult rv = nsToolkitProfileService::gService->Init();
2190 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2191 NS_ERROR("nsToolkitProfileService::Init failed!")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "nsToolkitProfileService::Init failed!"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp"
, 2191); MOZ_PretendNoReturn(); } while (0)
;
2192 delete nsToolkitProfileService::gService;
2193 return nullptr;
2194 }
2195 }
2196
2197 return do_AddRef(nsToolkitProfileService::gService);
2198}
2199
2200nsresult XRE_GetFileFromPath(const char* aPath, nsIFile** aResult) {
2201#if defined(XP_MACOSX)
2202 int32_t pathLen = strlen(aPath);
2203 if (pathLen > MAXPATHLEN4096) return NS_ERROR_INVALID_ARG;
2204
2205 CFURLRef fullPath = CFURLCreateFromFileSystemRepresentation(
2206 nullptr, (const UInt8*)aPath, pathLen, true);
2207 if (!fullPath) return NS_ERROR_FAILURE;
2208
2209 nsCOMPtr<nsIFile> lf;
2210 nsresult rv = NS_NewNativeLocalFile(""_ns, true, getter_AddRefs(lf));
2211 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2212 nsCOMPtr<nsILocalFileMac> lfMac = do_QueryInterface(lf, &rv);
2213 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2214 rv = lfMac->InitWithCFURL(fullPath);
2215 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2216 lf.forget(aResult);
2217 }
2218 }
2219 }
2220 CFRelease(fullPath);
2221 return rv;
2222
2223#elif defined(XP_UNIX1)
2224 char fullPath[MAXPATHLEN4096];
2225
2226 if (!realpath(aPath, fullPath)) return NS_ERROR_FAILURE;
2227
2228 return NS_NewNativeLocalFile(nsDependentCString(fullPath), true, aResult);
2229#elif defined(XP_WIN)
2230 WCHAR fullPath[MAXPATHLEN4096];
2231
2232 if (!_wfullpath(fullPath, NS_ConvertUTF8toUTF16(aPath).get(), MAXPATHLEN4096))
2233 return NS_ERROR_FAILURE;
2234
2235 return NS_NewLocalFile(nsDependentString(fullPath), true, aResult);
2236
2237#else
2238# error Platform-specific logic needed here.
2239#endif
2240}