File: | var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile/nsToolkitProfileService.cpp |
Warning: | line 990, column 7 Value stored to 'rv' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
66 | using 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 | |
75 | struct KeyValue { |
76 | KeyValue(const char* aKey, const char* aValue) : key(aKey), value(aValue) {} |
77 | |
78 | nsCString key; |
79 | nsCString value; |
80 | }; |
81 | |
82 | static 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 | */ |
94 | nsTArray<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 | |
101 | void 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 | |
142 | void 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 | |
236 | nsToolkitProfile::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 | |
270 | NS_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 | |
272 | NS_IMETHODIMPnsresult |
273 | nsToolkitProfile::GetRootDir(nsIFile** aResult) { |
274 | NS_ADDREF(*aResult = mRootDir)(*aResult = mRootDir)->AddRef(); |
275 | return NS_OK; |
276 | } |
277 | |
278 | NS_IMETHODIMPnsresult |
279 | nsToolkitProfile::GetLocalDir(nsIFile** aResult) { |
280 | NS_ADDREF(*aResult = mLocalDir)(*aResult = mLocalDir)->AddRef(); |
281 | return NS_OK; |
282 | } |
283 | |
284 | NS_IMETHODIMPnsresult |
285 | nsToolkitProfile::GetName(nsACString& aResult) { |
286 | aResult = mName; |
287 | return NS_OK; |
288 | } |
289 | |
290 | NS_IMETHODIMPnsresult |
291 | nsToolkitProfile::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 | |
321 | nsresult 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 | |
372 | NS_IMETHODIMPnsresult |
373 | nsToolkitProfile::Remove(bool removeFiles) { |
374 | return RemoveInternal(removeFiles, false /* in background */); |
375 | } |
376 | |
377 | NS_IMETHODIMPnsresult |
378 | nsToolkitProfile::RemoveInBackground(bool removeFiles) { |
379 | return RemoveInternal(removeFiles, true /* in background */); |
380 | } |
381 | |
382 | NS_IMETHODIMPnsresult |
383 | nsToolkitProfile::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 | |
399 | NS_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 | |
401 | nsresult 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 | |
410 | nsresult 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 | |
425 | NS_IMETHODIMPnsresult |
426 | nsToolkitProfileLock::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 | |
436 | NS_IMETHODIMPnsresult |
437 | nsToolkitProfileLock::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 | |
447 | NS_IMETHODIMPnsresult |
448 | nsToolkitProfileLock::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 | |
469 | NS_IMETHODIMPnsresult |
470 | nsToolkitProfileLock::GetReplacedLockTime(PRTime* aResult) { |
471 | mLock.GetReplacedLockTime(aResult); |
472 | return NS_OK; |
473 | } |
474 | |
475 | nsToolkitProfileLock::~nsToolkitProfileLock() { |
476 | if (mDirectory) { |
477 | Unlock(); |
478 | } |
479 | } |
480 | |
481 | nsToolkitProfileService* nsToolkitProfileService::gService = nullptr; |
482 | |
483 | NS_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 | |
485 | nsToolkitProfileService::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 | |
507 | nsToolkitProfileService::~nsToolkitProfileService() { |
508 | gService = nullptr; |
509 | mProfiles.clear(); |
510 | } |
511 | |
512 | void 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. |
549 | bool 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 | */ |
661 | nsresult 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 | |
734 | bool 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 | |
767 | nsresult 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 | |
791 | NS_IMETHODIMPnsresult |
792 | nsToolkitProfileService::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 | |
803 | struct ImportInstallsClosure { |
804 | nsINIParsernsINIParser_internal* backupData; |
805 | nsINIParsernsINIParser_internal* profileDB; |
806 | }; |
807 | |
808 | static 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 | |
830 | nsresult 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); |
Value stored to 'rv' is never read | |
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 | |
1054 | NS_IMETHODIMPnsresult |
1055 | nsToolkitProfileService::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 | |
1069 | NS_IMETHODIMPnsresult |
1070 | nsToolkitProfileService::GetStartWithLastProfile(bool* aResult) { |
1071 | *aResult = mStartWithLast; |
1072 | return NS_OK; |
1073 | } |
1074 | |
1075 | NS_IMETHODIMPnsresult |
1076 | nsToolkitProfileService::GetProfiles(nsISimpleEnumerator** aResult) { |
1077 | *aResult = new ProfileEnumerator(mProfiles.getFirst()); |
1078 | |
1079 | NS_ADDREF(*aResult)(*aResult)->AddRef(); |
1080 | return NS_OK; |
1081 | } |
1082 | |
1083 | NS_IMETHODIMPnsresult |
1084 | nsToolkitProfileService::ProfileEnumerator::HasMoreElements(bool* aResult) { |
1085 | *aResult = mCurrent ? true : false; |
1086 | return NS_OK; |
1087 | } |
1088 | |
1089 | NS_IMETHODIMPnsresult |
1090 | nsToolkitProfileService::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 | |
1099 | NS_IMETHODIMPnsresult |
1100 | nsToolkitProfileService::GetCurrentProfile(nsIToolkitProfile** aResult) { |
1101 | NS_IF_ADDREF(*aResult = mCurrent)ns_if_addref(*aResult = mCurrent); |
1102 | return NS_OK; |
1103 | } |
1104 | |
1105 | NS_IMETHODIMPnsresult |
1106 | nsToolkitProfileService::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 | |
1121 | void 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 | |
1141 | NS_IMETHODIMPnsresult |
1142 | nsToolkitProfileService::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. |
1179 | nsresult 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 | |
1207 | nsresult 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 | */ |
1237 | NS_IMETHODIMPnsresult |
1238 | nsToolkitProfileService::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 | |
1277 | static 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 | */ |
1298 | nsresult 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 | bool exists = false; |
1543 | |
1544 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
1545 | // We have a record of one! Use it. |
1546 | rv = rootDir->Clone(getter_AddRefs(file)); |
1547 | 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" , 1547); return rv; } } while (false); |
1548 | |
1549 | rv = file->AppendNative(buffer); |
1550 | 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" , 1550); return rv; } } while (false); |
1551 | |
1552 | rv = file->Exists(&exists); |
1553 | 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" , 1553); return rv; } } while (false); |
1554 | |
1555 | if (!exists) { |
1556 | printf_stderr( |
1557 | "Profile directory does not exist, create a new directory"); |
1558 | } |
1559 | } |
1560 | |
1561 | if (!exists) { |
1562 | nsCString saltedProfilePrefix = profilePrefix; |
1563 | SaltProfileName(saltedProfilePrefix); |
1564 | |
1565 | nsresult rv = BackgroundTasks::CreateNonEphemeralProfileDirectory( |
1566 | rootDir, saltedProfilePrefix, getter_AddRefs(file)); |
1567 | 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" , 1567)) { |
1568 | // In background task mode, NS_ERROR_UNEXPECTED is handled specially |
1569 | // to exit with a non-zero exit code. |
1570 | return NS_ERROR_UNEXPECTED; |
1571 | } |
1572 | *aDidCreate = true; |
1573 | |
1574 | // Keep a record of the salted name. It's okay if this doesn't succeed: |
1575 | // not great, but it's better for tasks (particularly, |
1576 | // `backgroundupdate`) to run and not persist state correctly than to |
1577 | // not run at all. |
1578 | rv = |
1579 | mProfileDB.SetString("BackgroundTasksProfiles", profilePrefix.get(), |
1580 | saltedProfilePrefix.get()); |
1581 | 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" , 1581); |
1582 | |
1583 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
1584 | rv = Flush(); |
1585 | 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" , 1585); |
1586 | } |
1587 | } |
1588 | } |
1589 | |
1590 | nsCOMPtr<nsIFile> localDir = file; |
1591 | file.forget(aRootDir); |
1592 | localDir.forget(aLocalDir); |
1593 | |
1594 | // Background tasks never use profiles known to the profile service. |
1595 | *aProfile = nullptr; |
1596 | |
1597 | return NS_OK; |
1598 | } |
1599 | #endif |
1600 | |
1601 | if (mIsFirstRun && mUseDedicatedProfile && |
1602 | !mInstallSection.Equals(mLegacyInstallSection)) { |
1603 | // The default profile could be assigned to a hash generated from an |
1604 | // incorrectly cased version of the installation directory (see bug |
1605 | // 1555319). Ideally we'd do all this while loading profiles.ini but we |
1606 | // can't override the legacy section value before that for tests. |
1607 | nsCString defaultDescriptor; |
1608 | rv = mProfileDB.GetString(mLegacyInstallSection.get(), "Default", |
1609 | defaultDescriptor); |
1610 | |
1611 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
1612 | // There is a default here, need to see if it matches any profiles. |
1613 | bool isRelative; |
1614 | nsCString descriptor; |
1615 | |
1616 | for (RefPtr<nsToolkitProfile> profile : mProfiles) { |
1617 | GetProfileDescriptor(profile, descriptor, &isRelative); |
1618 | |
1619 | if (descriptor.Equals(defaultDescriptor)) { |
1620 | // Found the default profile. Copy the install section over to |
1621 | // the correct location. We leave the old info in place for older |
1622 | // versions of Firefox to use. |
1623 | nsTArray<UniquePtr<KeyValue>> strings = |
1624 | GetSectionStrings(&mProfileDB, mLegacyInstallSection.get()); |
1625 | for (const auto& kv : strings) { |
1626 | mProfileDB.SetString(mInstallSection.get(), kv->key.get(), |
1627 | kv->value.get()); |
1628 | } |
1629 | |
1630 | // Flush now. This causes a small blip in startup but it should be |
1631 | // one time only whereas not flushing means we have to do this search |
1632 | // on every startup. |
1633 | Flush(); |
1634 | |
1635 | // Now start up with the found profile. |
1636 | mDedicatedProfile = profile; |
1637 | mIsFirstRun = false; |
1638 | break; |
1639 | } |
1640 | } |
1641 | } |
1642 | } |
1643 | |
1644 | // If this is a first run then create a new profile. |
1645 | if (mIsFirstRun) { |
1646 | // If we're configured to always show the profile manager then don't create |
1647 | // a new profile to use. |
1648 | if (!mStartWithLast) { |
1649 | return NS_ERROR_SHOW_PROFILE_MANAGER; |
1650 | } |
1651 | |
1652 | bool skippedDefaultProfile = false; |
1653 | |
1654 | if (mUseDedicatedProfile) { |
1655 | // This is the first run of a dedicated profile install. We have to decide |
1656 | // whether to use the default profile used by non-dedicated-profile |
1657 | // installs or to create a new profile. |
1658 | |
1659 | // Find what would have been the default profile for old installs. |
1660 | nsCOMPtr<nsIToolkitProfile> profile = mNormalDefault; |
1661 | if (mUseDevEditionProfile) { |
1662 | profile = mDevEditionDefault; |
1663 | } |
1664 | |
1665 | if (profile) { |
1666 | nsCOMPtr<nsIFile> rootDir; |
1667 | profile->GetRootDir(getter_AddRefs(rootDir)); |
1668 | |
1669 | nsCOMPtr<nsIFile> compat; |
1670 | rootDir->Clone(getter_AddRefs(compat)); |
1671 | compat->Append(COMPAT_FILEu"compatibility.ini"_ns); |
1672 | |
1673 | bool exists; |
1674 | rv = compat->Exists(&exists); |
1675 | 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" , 1675); return rv; } } while (false); |
1676 | |
1677 | // If the file is missing then either this is an empty profile (likely |
1678 | // generated by bug 1518591) or it is from an ancient version. We'll opt |
1679 | // to leave it for older versions in this case. |
1680 | if (exists) { |
1681 | bool result; |
1682 | rv = MaybeMakeDefaultDedicatedProfile(profile, &result); |
1683 | 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" , 1683); return rv; } } while (false); |
1684 | if (result) { |
1685 | mStartupReason = u"firstrun-claimed-default"_ns; |
1686 | |
1687 | mCurrent = profile; |
1688 | rootDir.forget(aRootDir); |
1689 | profile->GetLocalDir(aLocalDir); |
1690 | profile.forget(aProfile); |
1691 | return NS_OK; |
1692 | } |
1693 | |
1694 | // We're going to create a new profile for this install even though |
1695 | // another default exists. |
1696 | skippedDefaultProfile = true; |
1697 | } |
1698 | } |
1699 | } |
1700 | |
1701 | rv = CreateDefaultProfile(getter_AddRefs(mCurrent)); |
1702 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
1703 | #ifdef MOZ_CREATE_LEGACY_PROFILE1 |
1704 | // If there is only one profile and it isn't meant to be the profile that |
1705 | // older versions of Firefox use then we must create a default profile |
1706 | // for older versions of Firefox to avoid the existing profile being |
1707 | // auto-selected. |
1708 | if ((mUseDedicatedProfile || mUseDevEditionProfile) && |
1709 | mProfiles.getFirst() == mProfiles.getLast()) { |
1710 | nsCOMPtr<nsIToolkitProfile> newProfile; |
1711 | CreateProfile(nullptr, nsLiteralCString(DEFAULT_NAME"default"), |
1712 | getter_AddRefs(newProfile)); |
1713 | SetNormalDefault(newProfile); |
1714 | } |
1715 | #endif |
1716 | |
1717 | rv = Flush(); |
1718 | 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" , 1718); return rv; } } while (false); |
1719 | |
1720 | if (skippedDefaultProfile) { |
1721 | mStartupReason = u"firstrun-skipped-default"_ns; |
1722 | } else { |
1723 | mStartupReason = u"firstrun-created-default"_ns; |
1724 | } |
1725 | |
1726 | // Use the new profile. |
1727 | mCurrent->GetRootDir(aRootDir); |
1728 | mCurrent->GetLocalDir(aLocalDir); |
1729 | NS_ADDREF(*aProfile = mCurrent)(*aProfile = mCurrent)->AddRef(); |
1730 | |
1731 | *aDidCreate = true; |
1732 | return NS_OK; |
1733 | } |
1734 | } |
1735 | |
1736 | GetDefaultProfile(getter_AddRefs(mCurrent)); |
1737 | |
1738 | // None of the profiles was marked as default (generally only happens if the |
1739 | // user modifies profiles.ini manually). Let the user choose. |
1740 | if (!mCurrent) { |
1741 | return NS_ERROR_SHOW_PROFILE_MANAGER; |
1742 | } |
1743 | |
1744 | // Let the caller know that the profile was selected by default. |
1745 | *aWasDefaultSelection = true; |
1746 | mStartupReason = u"default"_ns; |
1747 | |
1748 | // Use the selected profile. |
1749 | mCurrent->GetRootDir(aRootDir); |
1750 | mCurrent->GetLocalDir(aLocalDir); |
1751 | NS_ADDREF(*aProfile = mCurrent)(*aProfile = mCurrent)->AddRef(); |
1752 | |
1753 | return NS_OK; |
1754 | } |
1755 | |
1756 | /** |
1757 | * Creates a new profile for reset and mark it as the current profile. |
1758 | */ |
1759 | nsresult nsToolkitProfileService::CreateResetProfile( |
1760 | nsIToolkitProfile** aNewProfile) { |
1761 | nsAutoCString oldProfileName; |
1762 | mCurrent->GetName(oldProfileName); |
1763 | |
1764 | nsCOMPtr<nsIToolkitProfile> newProfile; |
1765 | // Make the new profile name the old profile (or "default-") + the time in |
1766 | // seconds since epoch for uniqueness. |
1767 | nsAutoCString newProfileName; |
1768 | if (!oldProfileName.IsEmpty()) { |
1769 | newProfileName.Assign(oldProfileName); |
1770 | newProfileName.Append("-"); |
1771 | } else { |
1772 | newProfileName.AssignLiteral("default-"); |
1773 | } |
1774 | newProfileName.AppendPrintf("%" PRId64"l" "d", PR_Now() / 1000); |
1775 | nsresult rv = CreateProfile(nullptr, // choose a default dir for us |
1776 | newProfileName, getter_AddRefs(newProfile)); |
1777 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
1778 | |
1779 | mCurrent = newProfile; |
1780 | newProfile.forget(aNewProfile); |
1781 | |
1782 | // Don't flush the changes yet. That will happen once the migration |
1783 | // successfully completes. |
1784 | return NS_OK; |
1785 | } |
1786 | |
1787 | /** |
1788 | * This is responsible for deleting the old profile, copying its name to the |
1789 | * current profile and if the old profile was default making the new profile |
1790 | * default as well. |
1791 | */ |
1792 | nsresult nsToolkitProfileService::ApplyResetProfile( |
1793 | nsIToolkitProfile* aOldProfile) { |
1794 | // If the old profile would have been the default for old installs then mark |
1795 | // the new profile as such. |
1796 | if (mNormalDefault == aOldProfile) { |
1797 | SetNormalDefault(mCurrent); |
1798 | } |
1799 | |
1800 | if (mUseDedicatedProfile && mDedicatedProfile == aOldProfile) { |
1801 | bool wasLocked = false; |
1802 | nsCString val; |
1803 | if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mProfileDB.GetString (mInstallSection.get(), "Locked", val))), 1))) |
1804 | mProfileDB.GetString(mInstallSection.get(), "Locked", val))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mProfileDB.GetString (mInstallSection.get(), "Locked", val))), 1)))) { |
1805 | wasLocked = val.Equals("1"); |
1806 | } |
1807 | |
1808 | SetDefaultProfile(mCurrent); |
1809 | |
1810 | // Make the locked state match if necessary. |
1811 | if (!wasLocked) { |
1812 | mProfileDB.DeleteString(mInstallSection.get(), "Locked"); |
1813 | } |
1814 | } |
1815 | |
1816 | nsCString name; |
1817 | nsresult rv = aOldProfile->GetName(name); |
1818 | 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" , 1818); return rv; } } while (false); |
1819 | |
1820 | // Don't remove the old profile's files until after we've successfully flushed |
1821 | // the profile changes to disk. |
1822 | rv = aOldProfile->Remove(false); |
1823 | 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" , 1823); return rv; } } while (false); |
1824 | |
1825 | // Switching the name will make this the default for dev-edition if |
1826 | // appropriate. |
1827 | rv = mCurrent->SetName(name); |
1828 | 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" , 1828); return rv; } } while (false); |
1829 | |
1830 | rv = Flush(); |
1831 | 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" , 1831); return rv; } } while (false); |
1832 | |
1833 | // Now that the profile changes are flushed, try to remove the old profile's |
1834 | // files. If we fail the worst that will happen is that an orphan directory is |
1835 | // left. Let this run in the background while we start up. |
1836 | RemoveProfileFiles(aOldProfile, true); |
1837 | |
1838 | return NS_OK; |
1839 | } |
1840 | |
1841 | NS_IMETHODIMPnsresult |
1842 | nsToolkitProfileService::GetProfileByName(const nsACString& aName, |
1843 | nsIToolkitProfile** aResult) { |
1844 | for (RefPtr<nsToolkitProfile> profile : mProfiles) { |
1845 | if (profile->mName.Equals(aName)) { |
1846 | NS_ADDREF(*aResult = profile)(*aResult = profile)->AddRef(); |
1847 | return NS_OK; |
1848 | } |
1849 | } |
1850 | |
1851 | return NS_ERROR_FAILURE; |
1852 | } |
1853 | |
1854 | /** |
1855 | * Finds a profile from the database that uses the given root and local |
1856 | * directories. |
1857 | */ |
1858 | void nsToolkitProfileService::GetProfileByDir(nsIFile* aRootDir, |
1859 | nsIFile* aLocalDir, |
1860 | nsIToolkitProfile** aResult) { |
1861 | for (RefPtr<nsToolkitProfile> profile : mProfiles) { |
1862 | bool equal; |
1863 | nsresult rv = profile->mRootDir->Equals(aRootDir, &equal); |
1864 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && equal) { |
1865 | if (!aLocalDir) { |
1866 | // If no local directory was given then we will just use the normal |
1867 | // local directory for the profile. |
1868 | profile.forget(aResult); |
1869 | return; |
1870 | } |
1871 | |
1872 | rv = profile->mLocalDir->Equals(aLocalDir, &equal); |
1873 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && equal) { |
1874 | profile.forget(aResult); |
1875 | return; |
1876 | } |
1877 | } |
1878 | } |
1879 | } |
1880 | |
1881 | nsresult NS_LockProfilePath(nsIFile* aPath, nsIFile* aTempPath, |
1882 | nsIProfileUnlocker** aUnlocker, |
1883 | nsIProfileLock** aResult) { |
1884 | RefPtr<nsToolkitProfileLock> lock = new nsToolkitProfileLock(); |
1885 | |
1886 | nsresult rv = lock->Init(aPath, aTempPath, aUnlocker); |
1887 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv; |
1888 | |
1889 | lock.forget(aResult); |
1890 | return NS_OK; |
1891 | } |
1892 | |
1893 | static void SaltProfileName(nsACString& aName) { |
1894 | char salt[9]; |
1895 | NS_MakeRandomString(salt, 8); |
1896 | salt[8] = '.'; |
1897 | |
1898 | aName.Insert(salt, 0, 9); |
1899 | } |
1900 | |
1901 | NS_IMETHODIMPnsresult |
1902 | nsToolkitProfileService::CreateUniqueProfile(nsIFile* aRootDir, |
1903 | const nsACString& aNamePrefix, |
1904 | nsIToolkitProfile** aResult) { |
1905 | nsCOMPtr<nsIToolkitProfile> profile; |
1906 | nsresult rv = GetProfileByName(aNamePrefix, getter_AddRefs(profile)); |
1907 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1908 | return CreateProfile(aRootDir, aNamePrefix, aResult); |
1909 | } |
1910 | |
1911 | uint32_t suffix = 1; |
1912 | while (true) { |
1913 | nsPrintfCString name("%s-%d", PromiseFlatCStringTPromiseFlatString<char>(aNamePrefix).get(), |
1914 | suffix); |
1915 | rv = GetProfileByName(name, getter_AddRefs(profile)); |
1916 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1917 | return CreateProfile(aRootDir, name, aResult); |
1918 | } |
1919 | suffix++; |
1920 | } |
1921 | } |
1922 | |
1923 | NS_IMETHODIMPnsresult |
1924 | nsToolkitProfileService::CreateProfile(nsIFile* aRootDir, |
1925 | const nsACString& aName, |
1926 | nsIToolkitProfile** aResult) { |
1927 | nsresult rv = GetProfileByName(aName, aResult); |
1928 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
1929 | return rv; |
1930 | } |
1931 | |
1932 | nsCOMPtr<nsIFile> rootDir(aRootDir); |
1933 | |
1934 | nsAutoCString dirName; |
1935 | if (!rootDir) { |
1936 | rv = gDirServiceProvider->GetUserProfilesRootDir(getter_AddRefs(rootDir)); |
1937 | 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" , 1937); return rv; } } while (false); |
1938 | |
1939 | dirName = aName; |
1940 | SaltProfileName(dirName); |
1941 | |
1942 | if (NS_IsNativeUTF8()) { |
1943 | rootDir->AppendNative(dirName); |
1944 | } else { |
1945 | rootDir->Append(NS_ConvertUTF8toUTF16(dirName)); |
1946 | } |
1947 | } |
1948 | |
1949 | nsCOMPtr<nsIFile> localDir; |
1950 | |
1951 | bool isRelative; |
1952 | rv = mAppData->Contains(rootDir, &isRelative); |
1953 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && isRelative) { |
1954 | nsAutoCString path; |
1955 | rv = rootDir->GetRelativeDescriptor(mAppData, path); |
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 | rv = NS_NewNativeLocalFile(""_ns, true, getter_AddRefs(localDir)); |
1959 | 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" , 1959); return rv; } } while (false); |
1960 | |
1961 | rv = localDir->SetRelativeDescriptor(mTempData, path); |
1962 | } else { |
1963 | localDir = rootDir; |
1964 | } |
1965 | |
1966 | bool exists; |
1967 | rv = rootDir->Exists(&exists); |
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 | if (exists) { |
1971 | rv = rootDir->IsDirectory(&exists); |
1972 | 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" , 1972); return rv; } } while (false); |
1973 | |
1974 | if (!exists) return NS_ERROR_FILE_NOT_DIRECTORY; |
1975 | } else { |
1976 | nsCOMPtr<nsIFile> profileDirParent; |
1977 | nsAutoString profileDirName; |
1978 | |
1979 | rv = rootDir->GetParent(getter_AddRefs(profileDirParent)); |
1980 | 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" , 1980); return rv; } } while (false); |
1981 | |
1982 | rv = rootDir->GetLeafName(profileDirName); |
1983 | 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" , 1983); return rv; } } while (false); |
1984 | |
1985 | // let's ensure that the profile directory exists. |
1986 | rv = rootDir->Create(nsIFile::DIRECTORY_TYPE, 0700); |
1987 | 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" , 1987); return rv; } } while (false); |
1988 | rv = rootDir->SetPermissions(0700); |
1989 | #ifndef ANDROID |
1990 | // If the profile is on the sdcard, this will fail but its non-fatal |
1991 | 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" , 1991); return rv; } } while (false); |
1992 | #endif |
1993 | } |
1994 | |
1995 | rv = localDir->Exists(&exists); |
1996 | 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" , 1996); return rv; } } while (false); |
1997 | |
1998 | if (!exists) { |
1999 | rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700); |
2000 | 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" , 2000); return rv; } } while (false); |
2001 | } |
2002 | |
2003 | // We created a new profile dir. Let's store a creation timestamp. |
2004 | // Note that this code path does not apply if the profile dir was |
2005 | // created prior to launching. |
2006 | rv = CreateTimesInternal(rootDir); |
2007 | 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" , 2007); return rv; } } while (false); |
2008 | |
2009 | nsCOMPtr<nsIToolkitProfile> profile = |
2010 | new nsToolkitProfile(aName, rootDir, localDir, false); |
2011 | |
2012 | if (aName.Equals(DEV_EDITION_NAME"dev-edition-default")) { |
2013 | mDevEditionDefault = profile; |
2014 | } |
2015 | |
2016 | profile.forget(aResult); |
2017 | return NS_OK; |
2018 | } |
2019 | |
2020 | /** |
2021 | * Snaps (https://snapcraft.io/) use a different installation directory for |
2022 | * every version of an application. Since dedicated profiles uses the |
2023 | * installation directory to determine which profile to use this would lead |
2024 | * snap users getting a new profile on every application update. |
2025 | * |
2026 | * However the only way to have multiple installation of a snap is to install |
2027 | * a new snap instance. Different snap instances have different user data |
2028 | * directories and so already will not share profiles, in fact one instance |
2029 | * will not even be able to see the other instance's profiles since |
2030 | * profiles.ini will be stored in different places. |
2031 | * |
2032 | * So we can just disable dedicated profile support in this case and revert |
2033 | * back to the old method of just having a single default profile and still |
2034 | * get essentially the same benefits as dedicated profiles provides. |
2035 | */ |
2036 | bool nsToolkitProfileService::IsSnapEnvironment() { |
2037 | #ifdef MOZ_WIDGET_GTK1 |
2038 | return widget::IsRunningUnderSnap(); |
2039 | #else |
2040 | return false; |
2041 | #endif |
2042 | } |
2043 | |
2044 | /** |
2045 | * In some situations dedicated profile support does not work well. This |
2046 | * includes a handful of linux distributions which always install different |
2047 | * application versions to different locations, some application sandboxing |
2048 | * systems as well as enterprise deployments. This environment variable provides |
2049 | * a way to opt out of dedicated profiles for these cases. |
2050 | * |
2051 | * For Windows, we provide a policy to accomplish the same thing. |
2052 | */ |
2053 | bool nsToolkitProfileService::UseLegacyProfiles() { |
2054 | bool legacyProfiles = !!PR_GetEnv("MOZ_LEGACY_PROFILES"); |
2055 | #ifdef XP_WIN |
2056 | legacyProfiles |= PolicyCheckBoolean(L"LegacyProfiles"); |
2057 | #endif |
2058 | return legacyProfiles; |
2059 | } |
2060 | |
2061 | struct FindInstallsClosure { |
2062 | nsINIParsernsINIParser_internal* installData; |
2063 | nsTArray<nsCString>* installs; |
2064 | }; |
2065 | |
2066 | static bool FindInstalls(const char* aSection, void* aClosure) { |
2067 | FindInstallsClosure* closure = static_cast<FindInstallsClosure*>(aClosure); |
2068 | |
2069 | // Check if the section starts with "Install" |
2070 | if (strncmp(aSection, INSTALL_PREFIX"Install", INSTALL_PREFIX_LENGTH7) != 0) { |
2071 | return true; |
2072 | } |
2073 | |
2074 | nsCString install(aSection); |
2075 | closure->installs->AppendElement(install); |
2076 | |
2077 | return true; |
2078 | } |
2079 | |
2080 | nsTArray<nsCString> nsToolkitProfileService::GetKnownInstalls() { |
2081 | nsTArray<nsCString> result; |
2082 | FindInstallsClosure closure = {&mProfileDB, &result}; |
2083 | |
2084 | mProfileDB.GetSections(&FindInstalls, &closure); |
2085 | |
2086 | return result; |
2087 | } |
2088 | |
2089 | nsresult nsToolkitProfileService::CreateTimesInternal(nsIFile* aProfileDir) { |
2090 | nsresult rv = NS_ERROR_FAILURE; |
2091 | nsCOMPtr<nsIFile> creationLog; |
2092 | rv = aProfileDir->Clone(getter_AddRefs(creationLog)); |
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 | rv = creationLog->AppendNative("times.json"_ns); |
2096 | 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" , 2096); return rv; } } while (false); |
2097 | |
2098 | bool exists = false; |
2099 | creationLog->Exists(&exists); |
2100 | if (exists) { |
2101 | return NS_OK; |
2102 | } |
2103 | |
2104 | rv = creationLog->Create(nsIFile::NORMAL_FILE_TYPE, 0700); |
2105 | 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" , 2105); return rv; } } while (false); |
2106 | |
2107 | // We don't care about microsecond resolution. |
2108 | int64_t msec = PR_Now() / PR_USEC_PER_MSEC1000L; |
2109 | |
2110 | // Write it out. |
2111 | PRFileDesc* writeFile; |
2112 | rv = creationLog->OpenNSPRFileDesc(PR_WRONLY0x02, 0700, &writeFile); |
2113 | 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" , 2113); return rv; } } while (false); |
2114 | |
2115 | PR_fprintf(writeFile, "{\n\"created\": %lld,\n\"firstUse\": null\n}\n", msec); |
2116 | PR_Close(writeFile); |
2117 | return NS_OK; |
2118 | } |
2119 | |
2120 | NS_IMETHODIMPnsresult |
2121 | nsToolkitProfileService::GetProfileCount(uint32_t* aResult) { |
2122 | *aResult = 0; |
2123 | for (nsToolkitProfile* profile : mProfiles) { |
2124 | Unused << profile; |
2125 | (*aResult)++; |
2126 | } |
2127 | |
2128 | return NS_OK; |
2129 | } |
2130 | |
2131 | NS_IMETHODIMPnsresult |
2132 | nsToolkitProfileService::Flush() { |
2133 | if (GetIsListOutdated()) { |
2134 | return NS_ERROR_DATABASE_CHANGED; |
2135 | } |
2136 | |
2137 | nsresult rv; |
2138 | |
2139 | // If we aren't using dedicated profiles then nothing about the list of |
2140 | // installs can have changed, so no need to update the backup. |
2141 | if (mUseDedicatedProfile) { |
2142 | // Export the installs to the backup. |
2143 | nsTArray<nsCString> installs = GetKnownInstalls(); |
2144 | |
2145 | if (!installs.IsEmpty()) { |
2146 | nsCString data; |
2147 | nsCString buffer; |
2148 | |
2149 | for (uint32_t i = 0; i < installs.Length(); i++) { |
2150 | nsTArray<UniquePtr<KeyValue>> strings = |
2151 | GetSectionStrings(&mProfileDB, installs[i].get()); |
2152 | if (strings.IsEmpty()) { |
2153 | continue; |
2154 | } |
2155 | |
2156 | // Strip "Install" from the start. |
2157 | const nsDependentCSubstring& install = |
2158 | Substring(installs[i], INSTALL_PREFIX_LENGTH7); |
2159 | data.AppendPrintf("[%s]\n", PromiseFlatCStringTPromiseFlatString<char>(install).get()); |
2160 | |
2161 | for (uint32_t j = 0; j < strings.Length(); j++) { |
2162 | data.AppendPrintf("%s=%s\n", strings[j]->key.get(), |
2163 | strings[j]->value.get()); |
2164 | } |
2165 | |
2166 | data.Append("\n"); |
2167 | } |
2168 | |
2169 | FILE* writeFile; |
2170 | rv = mInstallDBFile->OpenANSIFileDesc("w", &writeFile); |
2171 | 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" , 2171); return rv; } } while (false); |
2172 | |
2173 | uint32_t length = data.Length(); |
2174 | if (fwrite(data.get(), sizeof(char), length, writeFile) != length) { |
2175 | fclose(writeFile); |
2176 | return NS_ERROR_UNEXPECTED; |
2177 | } |
2178 | |
2179 | fclose(writeFile); |
2180 | } else { |
2181 | rv = mInstallDBFile->Remove(false); |
2182 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv != NS_ERROR_FILE_NOT_FOUND) { |
2183 | return rv; |
2184 | } |
2185 | } |
2186 | } |
2187 | |
2188 | rv = mProfileDB.WriteToFile(mProfileDBFile); |
2189 | 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" , 2189); return rv; } } while (false); |
2190 | |
2191 | rv = UpdateFileStats(mProfileDBFile, &mProfileDBExists, |
2192 | &mProfileDBModifiedTime, &mProfileDBFileSize); |
2193 | 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" , 2193); return rv; } } while (false); |
2194 | |
2195 | return NS_OK; |
2196 | } |
2197 | |
2198 | already_AddRefed<nsToolkitProfileService> NS_GetToolkitProfileService() { |
2199 | if (!nsToolkitProfileService::gService) { |
2200 | nsToolkitProfileService::gService = new nsToolkitProfileService(); |
2201 | nsresult rv = nsToolkitProfileService::gService->Init(); |
2202 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
2203 | 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" , 2203); MOZ_PretendNoReturn(); } while (0); |
2204 | delete nsToolkitProfileService::gService; |
2205 | return nullptr; |
2206 | } |
2207 | } |
2208 | |
2209 | return do_AddRef(nsToolkitProfileService::gService); |
2210 | } |
2211 | |
2212 | nsresult XRE_GetFileFromPath(const char* aPath, nsIFile** aResult) { |
2213 | #if defined(XP_MACOSX) |
2214 | int32_t pathLen = strlen(aPath); |
2215 | if (pathLen > MAXPATHLEN4096) return NS_ERROR_INVALID_ARG; |
2216 | |
2217 | CFURLRef fullPath = CFURLCreateFromFileSystemRepresentation( |
2218 | nullptr, (const UInt8*)aPath, pathLen, true); |
2219 | if (!fullPath) return NS_ERROR_FAILURE; |
2220 | |
2221 | nsCOMPtr<nsIFile> lf; |
2222 | nsresult rv = NS_NewNativeLocalFile(""_ns, true, getter_AddRefs(lf)); |
2223 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
2224 | nsCOMPtr<nsILocalFileMac> lfMac = do_QueryInterface(lf, &rv); |
2225 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
2226 | rv = lfMac->InitWithCFURL(fullPath); |
2227 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
2228 | lf.forget(aResult); |
2229 | } |
2230 | } |
2231 | } |
2232 | CFRelease(fullPath); |
2233 | return rv; |
2234 | |
2235 | #elif defined(XP_UNIX1) |
2236 | char fullPath[MAXPATHLEN4096]; |
2237 | |
2238 | if (!realpath(aPath, fullPath)) return NS_ERROR_FAILURE; |
2239 | |
2240 | return NS_NewNativeLocalFile(nsDependentCString(fullPath), true, aResult); |
2241 | #elif defined(XP_WIN) |
2242 | WCHAR fullPath[MAXPATHLEN4096]; |
2243 | |
2244 | if (!_wfullpath(fullPath, NS_ConvertUTF8toUTF16(aPath).get(), MAXPATHLEN4096)) |
2245 | return NS_ERROR_FAILURE; |
2246 | |
2247 | return NS_NewLocalFile(nsDependentString(fullPath), true, aResult); |
2248 | |
2249 | #else |
2250 | # error Platform-specific logic needed here. |
2251 | #endif |
2252 | } |